From d494ea8cb59f6ff1af5faca9f5f651abcec618c0 Mon Sep 17 00:00:00 2001 From: dkaraush Date: Thu, 2 May 2024 20:38:57 +0400 Subject: [PATCH] update to 10.12.0 (4710) --- TMessagesProj/build.gradle | 1 + TMessagesProj/jni/lottie.cpp | 29 +- TMessagesProj/jni/webm_encoder.c | 23 +- .../src/main/assets/models/coin_border.png | Bin 2274 -> 2137 bytes .../src/main/assets/models/coin_stars.binobj | Bin 0 -> 34532 bytes .../src/main/assets/shaders/fragment3.glsl | 158 +- .../telegram/messenger/AndroidUtilities.java | 74 +- .../messenger/AnimatedFileDrawableStream.java | 6 +- .../telegram/messenger/AuthTokensHelper.java | 5 + .../org/telegram/messenger/ChatObject.java | 82 + .../messenger/ChatsWidgetService.java | 6 +- .../messenger/DatabaseMigrationHelper.java | 7 + .../telegram/messenger/DocumentObject.java | 33 +- .../java/org/telegram/messenger/Emoji.java | 9 + .../telegram/messenger/FileLoadOperation.java | 3 + .../telegram/messenger/FileRefController.java | 28 +- .../org/telegram/messenger/ImageLoader.java | 2 + .../org/telegram/messenger/ImageLocation.java | 16 + .../org/telegram/messenger/ImageReceiver.java | 3 + .../messenger/LocationController.java | 6 +- .../telegram/messenger/MediaController.java | 34 + .../messenger/MediaDataController.java | 76 +- .../org/telegram/messenger/MessageObject.java | 92 +- .../messenger/MessagePreviewParams.java | 2 +- .../messenger/MessagesController.java | 314 ++- .../telegram/messenger/MessagesStorage.java | 24 +- .../messenger/MusicPlayerService.java | 3 + .../messenger/NotificationCenter.java | 1 + .../NotificationDismissReceiver.java | 2 + .../messenger/NotificationsController.java | 275 ++- .../NotificationsSettingsFacade.java | 6 + .../messenger/PushListenerController.java | 86 +- .../telegram/messenger/SecretChatHelper.java | 1 + .../messenger/SendMessagesHelper.java | 23 +- .../org/telegram/messenger/SharedConfig.java | 12 +- .../messenger/TranslateController.java | 19 +- .../org/telegram/messenger/UserConfig.java | 4 +- .../org/telegram/messenger/Utilities.java | 4 + .../telegram/messenger/VideoEditedInfo.java | 1 + .../telegram/messenger/browser/Browser.java | 2 +- .../messenger/camera/Camera2Session.java | 6 + .../telegram/messenger/camera/CameraView.java | 9 +- .../ExtendedDefaultDataSource.java | 7 +- .../video/MediaCodecVideoConvertor.java | 2 +- .../telegram/messenger/video/WebmEncoder.java | 59 +- .../main/java/org/telegram/tgnet/TLRPC.java | 1245 +++++++++-- .../java/org/telegram/tgnet/tl/TL_stats.java | 14 +- .../org/telegram/tgnet/tl/TL_stories.java | 49 +- .../ui/ActionBar/ActionBarLayout.java | 34 + .../ui/ActionBar/ActionBarMenuItem.java | 3 + .../telegram/ui/ActionBar/BottomSheet.java | 17 +- .../ui/ActionBar/INavigationLayout.java | 1 + .../java/org/telegram/ui/ActionBar/Theme.java | 14 +- .../telegram/ui/ActionBar/ThemeColors.java | 13 +- .../ui/Adapters/DialogsSearchAdapter.java | 37 +- .../ui/Adapters/DrawerLayoutAdapter.java | 10 +- .../ui/Adapters/LocationActivityAdapter.java | 79 +- .../telegram/ui/Adapters/SearchAdapter.java | 17 +- .../main/java/org/telegram/ui/AvatarSpan.java | 22 +- .../ui/Business/BusinessIntroActivity.java | 129 +- .../ui/Business/ChatbotsActivity.java | 2 +- .../ui/Business/OpeningHoursActivity.java | 49 +- .../ui/Business/OpeningHoursDayActivity.java | 2 +- .../ui/Business/ProfileHoursCell.java | 10 +- .../org/telegram/ui/CacheControlActivity.java | 58 +- .../telegram/ui/Cells/AccountSelectCell.java | 2 +- .../org/telegram/ui/Cells/ChatActionCell.java | 19 +- .../telegram/ui/Cells/ChatMessageCell.java | 499 +++-- .../org/telegram/ui/Cells/CheckBoxCell.java | 369 +++- .../telegram/ui/Cells/CollapseTextCell.java | 76 + .../org/telegram/ui/Cells/DialogCell.java | 33 +- .../org/telegram/ui/Cells/EditTextCell.java | 4 +- .../telegram/ui/Cells/GraySectionCell.java | 2 +- .../org/telegram/ui/Cells/HeaderCell.java | 58 +- .../ui/Cells/NotificationsCheckCell.java | 91 +- .../ui/Cells/PhotoAttachPhotoCell.java | 6 + .../telegram/ui/Cells/PollEditTextCell.java | 261 ++- .../telegram/ui/Cells/ProfileChannelCell.java | 10 +- .../org/telegram/ui/Cells/RadioColorCell.java | 4 +- .../ui/Cells/ReactedUserHolderView.java | 2 +- .../telegram/ui/Cells/SendLocationCell.java | 156 +- .../ui/Cells/SettingsSuggestionCell.java | 28 +- .../ui/Cells/SharedPhotoVideoCell2.java | 132 +- .../ui/Cells/SharingLiveLocationCell.java | 39 +- .../telegram/ui/Cells/SlideIntChooseView.java | 49 +- .../telegram/ui/Cells/StickerSetNameCell.java | 12 +- .../java/org/telegram/ui/Cells/TextCell.java | 86 +- .../org/telegram/ui/Cells/TextCheckCell2.java | 1 + .../org/telegram/ui/Cells/TextColorCell.java | 15 - .../java/org/telegram/ui/Cells/UserCell.java | 4 +- .../telegram/ui/ChannelAdminLogActivity.java | 1347 ++++++++++-- .../org/telegram/ui/ChannelColorActivity.java | 74 +- .../ui/ChannelMonetizationLayout.java | 74 +- .../java/org/telegram/ui/ChatActivity.java | 488 +++-- .../org/telegram/ui/ChatEditActivity.java | 194 +- .../telegram/ui/ChatPullingDownDrawable.java | 203 +- .../telegram/ui/ChatRightsEditActivity.java | 5 + .../org/telegram/ui/ChatUsersActivity.java | 2 +- .../ui/Components/AdminLogFilterAlert2.java | 397 ++++ .../telegram/ui/Components/AlertsCreator.java | 260 +-- .../ui/Components/AnimatedEmojiDrawable.java | 5 +- .../ui/Components/AnimatedEmojiSpan.java | 10 +- .../ui/Components/AnimatedFileDrawable.java | 13 +- .../ui/Components/AnimatedTextView.java | 27 +- .../ui/Components/BackButtonMenu.java | 61 +- .../ui/Components/BlurredRecyclerView.java | 4 +- .../BottomSheetWithRecyclerListView.java | 280 ++- .../org/telegram/ui/Components/Bulletin.java | 12 +- .../ui/Components/BulletinFactory.java | 39 +- .../telegram/ui/Components/CacheChart.java | 6 +- .../ui/Components/ChatActivityEnterView.java | 26 +- .../ui/Components/ChatAttachAlert.java | 125 +- .../ChatAttachAlertLocationLayout.java | 2 +- .../ChatAttachAlertPhotoLayout.java | 58 +- .../Components/ChatAttachAlertPollLayout.java | 652 +++++- .../ui/Components/ChatGreetingsView.java | 9 + .../ui/Components/ColoredImageSpan.java | 13 +- .../ui/Components/CombinedDrawable.java | 15 + .../telegram/ui/Components/Crop/CropView.java | 8 +- .../Components/DeleteMessagesBottomSheet.java | 928 +++++++++ .../ui/Components/DialogsChannelsAdapter.java | 409 ++++ .../ui/Components/EditTextBoldCursor.java | 87 +- .../ui/Components/EditTextEffects.java | 6 +- .../ui/Components/EmojiPacksAlert.java | 4 +- .../org/telegram/ui/Components/EmojiView.java | 97 +- .../ui/Components/FlickerLoadingView.java | 41 + .../ui/Components/Forum/ForumUtilities.java | 17 +- .../ui/Components/ForwardBackground.java | 153 ++ .../ui/Components/InstantCameraView.java | 3 +- .../telegram/ui/Components/ItemOptions.java | 15 +- .../ui/Components/LinkSpanDrawable.java | 37 +- .../telegram/ui/Components/MediaActivity.java | 10 +- .../Components/OutlineTextContainerView.java | 6 +- .../telegram/ui/Components/Paint/Input.java | 20 +- .../Paint/ObjectDetectionEmojis.java | 459 +++++ .../ui/Components/Paint/Painting.java | 68 +- .../ui/Components/Paint/ShaderSet.java | 81 +- .../telegram/ui/Components/Paint/Swatch.java | 4 + .../Paint/Views/EntitiesContainerView.java | 1 + .../ui/Components/Paint/Views/EntityView.java | 4 +- .../Paint/Views/LPhotoPaintView.java | 260 ++- .../Components/Paint/Views/MaskPaintView.java | 462 +++++ .../Paint/Views/PaintWeightChooserView.java | 11 +- .../ui/Components/Paint/Views/PhotoView.java | 2 +- .../Paint/Views/StickerCutOutBtn.java | 85 +- .../Paint/Views/StickerMakerView.java | 941 +++++++-- .../Components/Paint/Views/TextPaintView.java | 2 +- .../ui/Components/PaintingOverlay.java | 44 +- .../ui/Components/PollVotesAlert.java | 49 +- .../ui/Components/PopupSwipeBackLayout.java | 2 +- .../Components/Premium/FeaturesPageView.java | 2 +- .../Premium/GLIcon/GLIconRenderer.java | 4 +- .../ui/Components/Premium/GLIcon/Icon3D.java | 3 +- .../Components/Premium/PremiumButtonView.java | 2 +- .../Premium/PremiumPreviewBottomSheet.java | 30 +- .../PremiumPreviewGiftToUsersBottomSheet.java | 38 +- .../Premium/boosts/SelectorBottomSheet.java | 2 +- .../boosts/UserSelectorBottomSheet.java | 126 +- .../boosts/adapters/SelectorAdapter.java | 32 +- .../cells/selector/SelectorBtnCell.java | 3 +- .../cells/selector/SelectorUserCell.java | 25 + .../ui/Components/RLottieDrawable.java | 1 + .../ui/Components/RLottieImageView.java | 12 +- .../ui/Components/ReactedUsersListView.java | 6 +- .../ChatCustomReactionsEditActivity.java | 38 +- .../ChatSelectionReactionMenuOverlay.java | 4 +- .../Reactions/CustomEmojiReactionsWindow.java | 101 +- .../Reactions/ReactionImageHolder.java | 20 + .../Components/ReactionsContainerLayout.java | 330 +-- .../ui/Components/ReplyMessageLine.java | 26 +- .../ui/Components/ScaleStateListAnimator.java | 5 + .../ui/Components/ScrollSlidingTabStrip.java | 2 +- .../Components/ScrollSlidingTextTabStrip.java | 4 +- .../ui/Components/SearchViewPager.java | 150 +- .../telegram/ui/Components/ShareAlert.java | 3 + .../ui/Components/ShareLocationDrawable.java | 47 +- .../ui/Components/SharedMediaLayout.java | 483 ++++- .../ui/Components/SharingLocationsAlert.java | 1 + .../org/telegram/ui/Components/SlideView.java | 4 + .../Components/StickerCategoriesListView.java | 30 +- .../ui/Components/StickerSetLinkIcon.java | 137 ++ .../telegram/ui/Components/StickersAlert.java | 246 ++- .../ui/Components/StickersDialogs.java | 78 +- .../ui/Components/SuggestEmojiView.java | 191 +- .../org/telegram/ui/Components/Switch.java | 2 +- .../telegram/ui/Components/ThanosEffect.java | 29 +- .../org/telegram/ui/Components/UItem.java | 180 +- .../ui/Components/UniversalAdapter.java | 347 +++- .../ui/Components/UniversalFragment.java | 26 - .../ui/Components/VideoSeekPreviewImage.java | 6 + .../org/telegram/ui/ContentPreviewViewer.java | 279 ++- .../java/org/telegram/ui/DialogsActivity.java | 90 +- .../org/telegram/ui/EditWidgetActivity.java | 6 +- .../ui/FragmentUsernameBottomSheet.java | 13 +- .../telegram/ui/GradientHeaderActivity.java | 2 +- .../org/telegram/ui/GroupCallActivity.java | 2 +- .../org/telegram/ui/GroupColorActivity.java | 18 + .../java/org/telegram/ui/LaunchActivity.java | 146 +- .../org/telegram/ui/LocationActivity.java | 247 ++- .../java/org/telegram/ui/LoginActivity.java | 1836 +++++++++++++---- .../NotificationsCustomSettingsActivity.java | 498 +++-- .../ui/NotificationsSettingsActivity.java | 191 +- .../ui/NotificationsSoundActivity.java | 11 +- .../org/telegram/ui/PassportActivity.java | 1 + .../org/telegram/ui/PaymentFormActivity.java | 27 + .../java/org/telegram/ui/PhotoViewer.java | 1660 ++++++++++++--- .../org/telegram/ui/PollCreateActivity.java | 799 ++++++- .../telegram/ui/PremiumPreviewFragment.java | 297 ++- .../java/org/telegram/ui/ProfileActivity.java | 881 ++++++-- .../telegram/ui/ProfileBirthdayEffect.java | 2 +- .../ui/ProfileNotificationsActivity.java | 4 +- .../org/telegram/ui/ReportAdBottomSheet.java | 2 +- .../ui/SelectAnimatedEmojiDialog.java | 156 +- .../ui/Stories/DialogStoriesCell.java | 4 + .../telegram/ui/Stories/PeerStoriesView.java | 44 +- .../ui/Stories/SelfStoriesPreviewView.java | 5 + .../ui/Stories/SelfStoryViewsPage.java | 4 + .../telegram/ui/Stories/StealthModeAlert.java | 39 +- .../ui/Stories/StoriesController.java | 166 +- .../ui/Stories/StoriesListPlaceProvider.java | 1 + .../org/telegram/ui/Stories/StoryViewer.java | 12 +- .../Stories/StoryWidgetsImageDecorator.java | 4 + .../recorder/ButtonWithCounterView.java | 20 +- .../ui/Stories/recorder/DownloadButton.java | 6 +- .../ui/Stories/recorder/EmojiBottomSheet.java | 291 ++- .../ui/Stories/recorder/PaintView.java | 7 +- .../ui/Stories/recorder/StoryRecorder.java | 13 + .../org/telegram/ui/UserInfoActivity.java | 37 +- .../org/telegram/ui/bots/BotBiometry.java | 4 +- .../drawable-hdpi/filled_extend_location.png | Bin 0 -> 858 bytes .../drawable-hdpi/filled_location_forever.png | Bin 0 -> 633 bytes .../drawable-hdpi/filled_stop_location.png | Bin 0 -> 1048 bytes .../res/drawable-hdpi/large_log_actions.png | Bin 0 -> 1629 bytes .../res/drawable-hdpi/left_status_profile.png | Bin 0 -> 1202 bytes .../res/drawable-hdpi/media_button_erase.png | Bin 0 -> 509 bytes .../drawable-hdpi/media_button_restore.png | Bin 0 -> 775 bytes .../res/drawable-hdpi/media_button_undo.png | Bin 0 -> 513 bytes .../drawable-hdpi/media_sticker_stroke.png | Bin 0 -> 1036 bytes .../main/res/drawable-hdpi/menu_birthday.png | Bin 0 -> 1159 bytes .../res/drawable-hdpi/menu_profile_colors.png | Bin 0 -> 1137 bytes .../menu_profile_colors_locked.png | Bin 0 -> 971 bytes .../res/drawable-hdpi/menu_storage_path.png | Bin .../drawable-hdpi/menu_username_change.png | Bin 0 -> 966 bytes .../res/drawable-hdpi/menu_username_set.png | Bin 0 -> 1056 bytes .../drawable-mdpi/filled_extend_location.png | Bin 0 -> 614 bytes .../drawable-mdpi/filled_location_forever.png | Bin 0 -> 447 bytes .../drawable-mdpi/filled_stop_location.png | Bin 0 -> 726 bytes .../res/drawable-mdpi/large_log_actions.png | Bin 0 -> 1138 bytes .../res/drawable-mdpi/left_status_profile.png | Bin 0 -> 808 bytes .../res/drawable-mdpi/media_button_erase.png | Bin 0 -> 410 bytes .../drawable-mdpi/media_button_restore.png | Bin 0 -> 567 bytes .../res/drawable-mdpi/media_button_undo.png | Bin 0 -> 429 bytes .../drawable-mdpi/media_sticker_stroke.png | Bin 0 -> 750 bytes .../main/res/drawable-mdpi/menu_birthday.png | Bin 0 -> 748 bytes .../res/drawable-mdpi/menu_profile_colors.png | Bin 0 -> 754 bytes .../menu_profile_colors_locked.png | Bin 0 -> 648 bytes .../res/drawable-mdpi/menu_storage_path.png | Bin .../drawable-mdpi/menu_username_change.png | Bin 0 -> 715 bytes .../res/drawable-mdpi/menu_username_set.png | Bin 0 -> 740 bytes .../drawable-xhdpi/filled_extend_location.png | Bin 0 -> 1127 bytes .../filled_location_forever.png | Bin 0 -> 866 bytes .../drawable-xhdpi/filled_stop_location.png | Bin 0 -> 1414 bytes .../res/drawable-xhdpi/large_log_actions.png | Bin 0 -> 2274 bytes .../drawable-xhdpi/left_status_profile.png | Bin 0 -> 1738 bytes .../res/drawable-xhdpi/media_button_erase.png | Bin 0 -> 662 bytes .../drawable-xhdpi/media_button_restore.png | Bin 0 -> 1053 bytes .../res/drawable-xhdpi/media_button_undo.png | Bin 0 -> 735 bytes .../drawable-xhdpi/media_sticker_stroke.png | Bin 0 -> 1393 bytes .../main/res/drawable-xhdpi/menu_birthday.png | Bin 0 -> 1497 bytes .../drawable-xhdpi/menu_profile_colors.png | Bin 0 -> 1513 bytes .../menu_profile_colors_locked.png | Bin 0 -> 1277 bytes .../res/drawable-xhdpi/menu_storage_path.png | Bin .../drawable-xhdpi/menu_username_change.png | Bin 0 -> 1489 bytes .../res/drawable-xhdpi/menu_username_set.png | Bin 0 -> 1623 bytes .../filled_extend_location.png | Bin 0 -> 1657 bytes .../filled_location_forever.png | Bin 0 -> 1255 bytes .../drawable-xxhdpi/filled_stop_location.png | Bin 0 -> 2170 bytes .../res/drawable-xxhdpi/large_log_actions.png | Bin 0 -> 3491 bytes .../drawable-xxhdpi/left_status_profile.png | Bin 0 -> 2573 bytes .../drawable-xxhdpi/media_button_erase.png | Bin 0 -> 891 bytes .../drawable-xxhdpi/media_button_restore.png | Bin 0 -> 1489 bytes .../res/drawable-xxhdpi/media_button_undo.png | Bin 0 -> 898 bytes .../drawable-xxhdpi/media_sticker_stroke.png | Bin 0 -> 1913 bytes .../res/drawable-xxhdpi/menu_birthday.png | Bin 0 -> 2240 bytes .../drawable-xxhdpi/menu_profile_colors.png | Bin 0 -> 2194 bytes .../menu_profile_colors_locked.png | Bin 0 -> 1870 bytes .../res/drawable-xxhdpi/menu_storage_path.png | Bin .../drawable-xxhdpi/menu_username_change.png | Bin 0 -> 2097 bytes .../res/drawable-xxhdpi/menu_username_set.png | Bin 0 -> 2281 bytes TMessagesProj/src/main/res/raw/bubble.json | 1 + .../src/main/res/raw/thanos_vertex.glsl | 27 +- .../src/main/res/values-ar/strings.xml | 1 + TMessagesProj/src/main/res/values/strings.xml | 207 +- gradle.properties | 4 +- 294 files changed, 20468 insertions(+), 4408 deletions(-) create mode 100644 TMessagesProj/src/main/assets/models/coin_stars.binobj create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/filled_extend_location.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/filled_location_forever.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/filled_stop_location.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/large_log_actions.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/left_status_profile.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/media_button_erase.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/media_button_restore.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/media_button_undo.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/media_sticker_stroke.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_birthday.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors_locked.png rename {TMessagesProj_AppStandalone => TMessagesProj}/src/main/res/drawable-hdpi/menu_storage_path.png (100%) create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_username_change.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_username_set.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/filled_extend_location.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/filled_location_forever.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/filled_stop_location.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/large_log_actions.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/left_status_profile.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/media_button_erase.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/media_button_restore.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/media_button_undo.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/media_sticker_stroke.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_birthday.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors_locked.png rename {TMessagesProj_AppStandalone => TMessagesProj}/src/main/res/drawable-mdpi/menu_storage_path.png (100%) create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_username_change.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_username_set.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/filled_extend_location.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/filled_location_forever.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/filled_stop_location.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/large_log_actions.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/left_status_profile.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/media_button_erase.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/media_button_restore.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/media_button_undo.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/media_sticker_stroke.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_birthday.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors_locked.png rename {TMessagesProj_AppStandalone => TMessagesProj}/src/main/res/drawable-xhdpi/menu_storage_path.png (100%) create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_username_change.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_username_set.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/filled_extend_location.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/filled_location_forever.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/filled_stop_location.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/large_log_actions.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/left_status_profile.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/media_button_erase.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/media_button_restore.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/media_button_undo.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/media_sticker_stroke.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_birthday.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors_locked.png rename {TMessagesProj_AppStandalone => TMessagesProj}/src/main/res/drawable-xxhdpi/menu_storage_path.png (100%) create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_change.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_set.png create mode 100644 TMessagesProj/src/main/res/raw/bubble.json diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index b816b715f..808586132 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -48,6 +48,7 @@ dependencies { implementation 'com.google.guava:guava:31.1-android' implementation 'com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1' + implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8' constraints { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") { because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib") diff --git a/TMessagesProj/jni/lottie.cpp b/TMessagesProj/jni/lottie.cpp index 039beb5e2..46a1fcf05 100644 --- a/TMessagesProj/jni/lottie.cpp +++ b/TMessagesProj/jni/lottie.cpp @@ -182,9 +182,34 @@ JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_getFramesCount(J delete info; return 0; } - long frameCount = info->animation->totalFrame(); + long framesCount = info->animation->totalFrame(); delete info; - return (jlong) frameCount; + return (jlong) framesCount; +} + +JNIEXPORT jdouble Java_org_telegram_ui_Components_RLottieDrawable_getDuration(JNIEnv *env, jclass clazz, jstring src, jstring json) { + auto info = new LottieInfo(); + char const *srcString = env->GetStringUTFChars(src, nullptr); + info->path = srcString; + if (json != nullptr) { + char const *jsonString = env->GetStringUTFChars(json, nullptr); + if (jsonString) { + info->animation = rlottie::Animation::loadFromData(jsonString, info->path, nullptr, FitzModifier::None); + env->ReleaseStringUTFChars(json, jsonString); + } + } else { + info->animation = rlottie::Animation::loadFromFile(info->path, nullptr, FitzModifier::None); + } + if (srcString) { + env->ReleaseStringUTFChars(src, srcString); + } + if (info->animation == nullptr) { + delete info; + return 0; + } + double duration = info->animation->duration(); + delete info; + return (jdouble) duration; } JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_createWithJson(JNIEnv *env, jclass clazz, jstring json, jstring name, jintArray data, jintArray colorReplacement) { diff --git a/TMessagesProj/jni/webm_encoder.c b/TMessagesProj/jni/webm_encoder.c index 99a0c2755..67f32f5fa 100644 --- a/TMessagesProj/jni/webm_encoder.c +++ b/TMessagesProj/jni/webm_encoder.c @@ -70,8 +70,9 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_video_WebmEncoder_createEnco ctx->codec_ctx->time_base = (AVRational){ 1, fps }; ctx->codec_ctx->framerate = (AVRational){ fps, 1 }; ctx->codec_ctx->bit_rate = bitrate; - ctx->codec_ctx->gop_size = 10; - ctx->codec_ctx->max_b_frames = 1; + ctx->codec_ctx->rc_min_rate = bitrate / 8; + ctx->codec_ctx->rc_max_rate = bitrate; +// ctx->codec_ctx->rc_buffer_size = 2 * bitrate; if (ctx->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { ctx->codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -185,6 +186,9 @@ JNIEXPORT jboolean JNICALL Java_org_telegram_messenger_video_WebmEncoder_writeFr pkt.stream_index = ctx->video_stream->index; ret = av_interleaved_write_frame(ctx->fmt_ctx, &pkt); + if (ret < 0) { + LOGE("vp9: failed to av_interleaved_write_frame %d", ret); + } av_packet_unref(&pkt); } @@ -200,13 +204,16 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_video_WebmEncoder_stop( return; } - avcodec_send_frame(ctx->codec_ctx, NULL); + int ret; + ret = avcodec_send_frame(ctx->codec_ctx, NULL); + if (ret < 0) { + LOGE("vp9: failed to avcodec_send_frame %d", ret); + } AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; - int ret; while (1) { ret = avcodec_receive_packet(ctx->codec_ctx, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { @@ -220,10 +227,16 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_video_WebmEncoder_stop( pkt.stream_index = ctx->video_stream->index; ret = av_interleaved_write_frame(ctx->fmt_ctx, &pkt); + if (ret < 0) { + LOGE("vp9: failed to av_interleaved_write_frame %d", ret); + } av_packet_unref(&pkt); } - av_write_trailer(ctx->fmt_ctx); + ret = av_write_trailer(ctx->fmt_ctx); + if (ret < 0) { + LOGE("vp9: failed to av_write_trailer %d", ret); + } if (ctx->frame) { av_frame_free(&ctx->frame); diff --git a/TMessagesProj/src/main/assets/models/coin_border.png b/TMessagesProj/src/main/assets/models/coin_border.png index d5ea95fb1e08b6f66e87f53fc8e2248907bd85d3..d68e1299f328301fc250a780b7495e1cb006daac 100644 GIT binary patch delta 2059 zcmV+m2=w>j5!n!sWq$~CQchC<{}SI~IJb@Cupi3+00+xSL_t(|+U;FSbK5o$=2N-~ zqAXo0D`Q#11ckALLj|J;07X5fLQ*O`USEAH|p|B$(Pu> z|70Lyg=>7(<(E<{P~o>q&2O_gCj2aKi)M;9eEct#@7W9wepc$oQNRkn>IsShcKB6~ z*e(3{ksW^Zvwstc^}BODoWMJU$FB8LBxDB!`1g$AvlJZuOMQqS)fIq;f5#xEXbMCf z^5xr(X*(a(Bb!*PuZTue>ksLZ+ThP2`HQ9iARF7@AM!wGt=Ycp3JU(*_f66+CgvVv z7;GGL;V-{j@ky8?kfGiB@5P*C+PVOd;nZsVHv*HPu74N|8Qz>DPh(cNQkhOZAY^#7 zIzJo$3(uSY5Hc+7&W{9uIROA%WMQ8M06Q_>!X!fg_F34sg+OJ;G!3nQg?$tN@Zn6m zH*jdWb@=`@0D`V<9yT=HxSX#F0Q_}3hJVn|)aiWH0Ek%^@ zGxn$eV1J!}0l6r2#vU~QxE?dWz>EX@%DFS|>c5bIneTf41^^r)w>H{54TgZ!>jMBE zDzUn)L&Zg|jBnUjhQd18!*P+rxs4hhe8QIYl^bpoTIVur9K+0B78s5Se5(=KH(Nhs zc9WYA78mhtn4Fvd@LZ*#{cuzu!mveZhJo`7n}2l3xJY=Sx+{7HK;X;}3>ucmGR*SO z1%Qo)VZsvO4zv68JpSp@1PmS*#j+Im{!sllKkqfyL<58+vKm;)qTL{=(}e^GOFkRp z_e=m(j_yTNh1&h#o&fL^Sv|I1B!OmT!8^j2T>OW%hovF z5-6a+z{j;it@&#VaLzmuIl~}Z(I~(J1?d}1NHAD4bFvfO`i@8enbj3JO^-}AQh`@G z1-vM;mzXgn^+p+GluA>4>!op{v@tVJPXv*nL3o$S}$bd$#yb z&jxe@-ESE%_*zrmyUro_6a*Kp=6}ebv&=r5UDzTsSOv;UI0wGG#OVI2I6#~9HS8Mr zDg-4ZnKU$oHAZS7A#OV~)zeE1v0RqSL3v(;5K;jJU|C|4^bTPL+QV0YnSYj8H`V|Y z1MMd0)>gCHPbm@<1-jjKb=h+QnXysKfMuok+%P?FL337`0#1&)gb5S=;|Yy~ubPZ~bt1b>~cnV-t^K0G5TV0r;hRkH3c#BE^gy(&S6n5QheB>1jk z;njfv1PvDc#7mV%4*U0FMu>2JvCHQbhY6Dd#u~V2I4Dt)wLM29MTCfuD$RRXaLN!U zGVWu+5aWW~b>CfPImRLseQ3`Ryo9*#KDP;muQ=^9dj&>AuFxR)=6}K=hQBVl9$hSq zQ@E+ib~b+~NAlOJv+NcY4$<1eYZgu(-M%~cLR9{cQ9{IR%dSeuUvv=Qy6RD3T(#z- zM~z#(nTa5EAnqGW6}OEdXw<@1g4{){-e^RUJXtIAPNIOCGa^wyE#}a)*C{tPfM$z1 z3%X?AV<5q#G(M+VamH_q{EBDjn zx+9pYTm)wb_sYtbYJ9j+!qo`S4ymgvige2=BnY0=yRLmemw!+@iYkBcCwX}LUg%vU zC7@Ss%x-DxAqha!L`DLp&eF2q(L%${RfpG~zP~*igbf*%T+TjBfm1Y$U7RD>sAPS? z%1ohu2P?jii7ddg6M1h6$cO(SFm3?nJ$3@2lsIuW)y52^qP=%%5M)Tr-G%-3;|TA! z=mh(isWI8zet*Ilzve+LRr|uMcjAMIyz`Siyj{yrpJc#>QL$10U-RJYIbOR@JzS|$ zwKHj+op*8rL*d=uwE~YGmDCD&qXIv=0tul4f|~b~XHLb-lXR7xUBuOg0x%Z5C{t;L p4|EF1qu+NPrM&#{=>5;-A3qK9x>2gUhyVZp07*qoL)itJk03q%rX${>}DWW(Hz;{SUiOYF0xawSPTpKVrRs zQlhUvQ}8hm*8TbC@>4!70Py=1cwpdAiXUPw-V62 zHRAAw0Dc$xcYhH>NR;64lME0CB*&WZS7}VnfQ0`C>}zrcN&|lB=QD5<+3Pp&S>WHn zFU%FiuSgk?@R#tbRb?nJ)o>4gY5l70&#M6PGb6YD8^!J@9}tEEQ^fgpchWF8!#QSs zb0ZTVW1zsSZ)wPc${Wkz2U=e#logaoL#cky`AemcxPOmHym5@ce`kSEt#IxPkFnSj z8fCFmoZ*Vh`#j)U2~kJji%LBB004lt-#G&S{)&MG08rGLGAyQ^#cHyWN2>c&K02QC!sM*@v3y@ih=C~pI9Yx(*9$HegEFs4VZO?QD>M_OKZek zUW9nypgs1jDO6fIBkuB|9Mgij3rrF%A0x<%s(;Q7enJ4yCJ7V#;#_;;W}&)(P50$0 zpkx4KLSk2cxbFe569s1S9l8QF=4dYOY8jc15I0OvBuoTGt6<;)92W`G+B|>L8v``* zbe)#m8w^Z3bl?f7`>dc)&%fwJgNNRk`@HB7#-9(pHQ3m#hw~EIy%w9|C1T1FS$G2- zLw_=G0dys@ch_I80M4w*7e~je8mhr?^o!~NptJOi^8uWt91W{t;09ujeo;1%esZ*H zc3SXa|87OiK#YgOR23=<(k;VE8OsDsX&;m+Y1=hwY<|M#3UEC@VURNoPvkZjaLq16 zws|SG(ScH+adFBvMAen)W@a4SurSbt?0*eqQ2tvrycg1-{C8lmWVggR3>NH`cmM_! zizOa_0h1-x6Zj>&CAPvqFi#S8Rg{J^CLV%8;$fV%fc?D4!$5BcJ#)rs2sIdNew8th z!{E8a;F6tz4hGG)l3fdx7}e8EcNYZ+ubTxGHb=lpwXdOe0|uUUJ7iUN;){WH%zt1R zc%-{8e=UMN?P*W{BRZIPJ^mP-4B&R)C;k}7J$sIkzokGmfZ6zBp!OWT1WFgw7Xzo> zR#Ust=Yntse$T)!=$&5%ezZe~+m!MnI}E#C{JP6&&v;dFE|b^-+Z3cmUo8*@@NFgH z6!O&#RQ!wLrLr9#u_yHztYb{%c7F<2Yyvj)9=~r9araYL2Zsp(&;ZpB?*&_E5aCJ} z&V{hfg%N~-$bRG@PjC|1&hNqT#DM@DYB58BFCLWhl)k{0X-L1jzWft-p@Q5RsRC&C z7Md#+2GkOGHeJHGk|`{SC2#@nTeCkYu^!Z*v6LzEi7$Yw4J`zo!0#%I;(u~P3W69U zA(cKOx{!R4MQ3AaXF_yJwl&pcF0qorZhg|n%j-XKMF<6@8h~b20bIf%Y_gE{y}|V= zt=6TFQ|I_G#y(LqXX2kEIzJ>p^&HmQQoaazQLlHD)|w zj#rexBCv_|QV8Z=52oVNhw z4xW+w%Emwrps#qJM(9o-4F;A&(MA9Sm6@XUfj z=xoBzXmUbFl~JDwuX9cgBJ7YOP^YABB!_qrsNG@X7{RiwNw@tI`YE{BF6lXWL?+!Z z&H>L9Ry1Jt+Q(j=Xs@6iFncK<3bb8z7_^ZqLIoNY6I4s68#i!^T91cPj*7kdq_M2i z%2;v6%7F@olx3zw<9|TOh6iDdrE2x2MOCu$x)3|YTMZTB4DBPGZu~& zoEtjfjrq`O#yncpzcar9DCFIaI8t|XA`gSv1#ITUK3<%!v=tq~;5fa$Tv!~`S{h@z zLe<
9N!kd%SSnu1CDNBPusY@gJqm9`bt4V3mjEg=WG2!BBs4&;C=3`D}7fk_b% z+JQ`e%Lc7q5n95n|9!l{W|lw&kI)yiSDzq404-xeZ`d6&HD{JU)10tx*Z-Ea&cO(z z#e{Kr&p@I*I0+v%qHLc_Irnd!UA-RlZVvTgM3@>$RSR?Tkt@(qr1Hj~R2-WOEaiWq z3JFV~;Zyzm27kbTDnD0}o)XWEGRnLpQhqzNQhW|9B3U>Rs($bmNlV7G$+7mhy?kh_ zD;VvxgRVS~=@)$XGgm4#6>*U&{Y51*AurPvLvN{d=7};lABiCjYKGzF+Rj1O!C8

iBCz#&<*Ci_undgZ8E^O;<77^)hYvz$5?h zG7;zg8-V{M26nX&&kT6oISqY38WIR0s3-V-Cq(q{c9C8-TLyk*u=aL-8w*^Jp79Sd XF7;;Wkq$8400000NkvXXu0mjfoi`jn diff --git a/TMessagesProj/src/main/assets/models/coin_stars.binobj b/TMessagesProj/src/main/assets/models/coin_stars.binobj new file mode 100644 index 0000000000000000000000000000000000000000..61a562721051e0a32b5fa503360655d05326ee98 GIT binary patch literal 34532 zcmZ{r2Ygh;_x7_JiZtm+C!u$wh}44G#-5#Q&`-dUghzwUfKC-d;#XC}AJxp(gg5fRy=oOz4lGPJ&uy#NXDVj0zNQ;18P#|OM*){=x zWZR6_S6mI~^*b{rjJaj>>^>_q;tw}AdfvNlX3V`k!RQ4wvt)djTs)vhmde+F(*Hib*ysgUJVCx- z^z@*ALCq)ZJpMMtdpc8|!2B7R{hi*t?Tp`6&*;9(iaD`Irx+b`Mme#aaPHvgw`-0w zZqN;*`)9f8jIBB&z<2naF*kI``S*9Nw^fvV-aa(J83)rv0&Zcml7Q-j-C#j_!}{gt;I3hq~x$XI9G zkjZ9jl^@qTv0Xn2%u^;lczhbPKjw^&56tgN``nrQdnx0Q?MY0}VsumAF=u-3T1Gdk zFx{Dc7}q4Wt@(==o$1%x8Qo&e@E~s)yDsRL<74NUdAzG{)zkZNe((9`>}=~xSv$<= zl=qtW=Dt|p%(JLoci)_8@L>K$Z@2Z$`rpd|oxaS;|AZ9yLF77dGIISut`xyC--0BtN(JgfUZ*4SLe@`Mko2N`D%G$ z0=n+AzNc?Q8a-pfq#&Q+)Cu}$WIGX@CvoLy->|N48-K#C?|f5E$-2Jhe`DIs;Py-y zunOB**YNSnTLiWrp7EVC2lh+!iYvZZX9L?aVQ4eooS9<+^UQiWaD3oNNc+^6(x#E& zi60E{t%^8j^o(rBeS4B{tl*j9i}QVSuvI{RP}sL$r5T-s{o4Q8h=5K%7Uap53I+Xg zeC#~qzFg-oa3LE0Oa8dodHngJCmB8Ui&yczTl5K0WILK$DejW7B`0ZkFp5&ww{v7c`jeqvRXZ(3@OU}IK zPw9Kw-JW~?Mc&E&g55tbe9@>>f1&1Br|>LVs{Bt)?HJG_5Bm!r@dw8KbHQI^$IgK6 z-NRqBVuI1L_bm1ozg)rS57VS)jM!Gj`PQ*Xmd(pw+Mb+GVd9J$-Fo zf9)|?FS5T`KMC^01v6d$B|najJI^KmRDU0Tnb^SmaZ?-ki$5HQv6uYgj%;$b=aPTy z)MRYu4#Qu4Zw|IUBcMB|@4)+(Z2f zX2|-&Jn#O5<0IF@$&4*uto6_P`Fo=evONj@#HGcIKGeFdf7_R<-nKQG!O$iMg_ThK4Z$DPM%Ty=|o?rGVcRHw$e&-`;n4=}n? z_F4X!Q9l}8?nZn6)auCL@RS=h)SobWq|s#)Ci)YicNtx#$;bZqKV_|@I;C^w4f5y` zOW_}7c+}gygY%Sl@hkt#{BnL%okGVu_~&%rZgjSu{{*+^i9EIa^9o1~Om(t8oy9+I zw%6z^XXE|ztFH*~n&WOugmdFbxKSc zgk_13-=Uk zkBY7ApO;T^W~%dK`_G-XTJM8C=y)dgc9yQdy)XTs@4_r#$%UMECp>BR)rQN#uNZy#wIAUB!RTM&DhB7d(08u$ z&avf&pS*j( z&f;OR77qIMSM``sm>VRai_p1Q;Z&Uf2~uX&Ed&FHBa{d~8p ze-_Y>FZph6c-81>u~mK7|4K4CvB0ao>o3Lz^tQc0KE1Lh=$}3$J~&U3_qvn$w&ed* zXI8tePR^NIj9!?tRB(G1ZY>nt&Xnk~!R=3J-8{HoDN(hY{JjHfZQ-WDPJs^c{UX&_ z_{7BE@tM`Euk+LbJo|yq`2D<7vbN7?Y>!j5aMpmXeB7zl^J$|KcXV^A*L*La3%u%7 zpHkiEX|FF0@@bw9K|hXo^G}A)BSy3 zlji1LZ|0|ay}j=X=lj0Z!uc7%YT^7mV6||5Hn3VaKPOl%oSzx27S7KPRtx8639E(k zbA{Ey=@}!a!9$)m?6XJ2UynkbJ?wLcaDEQ4T6oAaiTiwFI6a@(XBFZ6tYWorer~Z^ zI6uQ!Eu5cctQOACHdYJg=Nzkr^D~dt!uk2fYT^7WWVLX9F0xuUKO6y(wzX|8(H>-v7vz*n!`MJ(&;rxteweXPVJ@?tqaDMi4wc+#}XrBqq{Pav{pAW(P z{C(N#h)2GV@6Psnv~d0&ZME=_@6_)1Ys2aLb)u_-@EZ$)qDpR9`YUB z{XT9ue;;?X;q=|yeoq(9-_xxY&fnRs7S7+_tri~gUEcj(Z#aLiceUaC9pBZ4)A#*F zt`?rc-~C-}IK2l*akX%MCt$U3em`Kf@Q`-}?t25n`MrUw4X1YqGh8h^~)x!B5h1J4C-dDKqE)3^)7p^v( z-ecHz8fN}~-)Z>m`wj4r_w)8$eZ*fkLf+Ne_x8d=-rKwH@C~PT_=&C-9`ZileYbBo zzuR}U;q;z=nybzH{LbIihSU51L{|&vT7cEUxh`O}@Q@mTTQ4x2>jkbhoN5OPTrHgI z2v!RZsVTVi1;e?%;A+FE)?n)n!ny8XwQ#OMSS_6E5mpNisZF?b3d6Zh;cCOVX5nhX zxqjhl!>N|B+SS6ju3@!su5nl`oa-G{3lFJ%xOEW2xenrL!>J~c;%ebsAF*0^NUg-J zn;6b@6IUDlZw&?4QlOp!?&tUOR!2O-`yqN)Z?$lKZ*R5mkazg*`+URseZH#==Xd+A zHk{w{yV`Ji=WpNt3+MO$Rtuj)wE(Myb6vn{;UP5ww_ad4)eDkcEj*-l;MNfgr#gbX zdzYGmkd{6=Ng37!nqz{wQ#OYSS>uHPT|%p4Ck7K zs|~06g{@_n`Kgv+>l(t}pt^?D!nwv_wQ#O?SS`mnr1s&~K@8_Qh^q~!n#c@S+w&Ey zkGQoG!>Lx1xO#YT;bdv|2dVH?0=VwN9&z zpX#3dTy5s38fc8Gg>yaBYT;ZPwOTmWNv#$hQZseyr-oDgw56+sb1l_s;apd>S~%BO ztrpJpR;z_`?bT}GT!*zP7w z>%79NQJvRn;au~zS~%B#trpI;V5^05UD#^jTqCwxIM<7<7S6R}tA&Tuk=>fI;Z#$$ z^=0so_w)8$eZ-?&{H{Kz!9(8L+jscF`5nI1!ufr^)x!DRzSY9{J-^k$`JKPj!ukEb z)xxkd{6=Ng37W`C(3VQUk@xi(?7aIRBWEu3o>Rtx9)h1J5jmSMGUu4`B=oNF9b3#WQV zP=klmK5QLCIM+d}7S1&htA&TuN8DP8;an?mwc%7Zu{9JkKh;odJw-UzQ>>QvAzWLr zS~%BPtQHxprfOO7_$Z)CwCAwO8NIl4{4H-_gAzLRB&UGTIg>%iwYT+UE zBe#}hIMtGDT}gOIUCFI68O}8(R~t_CCR=+l^K;as1xT6jpU z%B@=&PIas4t`;6r!*c6chEqKY=g!o&goo6&+&Y)xROhlaFX2@43Tp6(2yauhrcYK~ z>&#@e=H@b8>u9oC`({=1@3q$(=-RnS?qwCR^Oj@Atpu2kz6-O&wZ3{&gox6qAp=2oj3Rnm>})l;(lx?W)W zO@F73*6~%<+Uplhzou`L*4xLbwUd{dUXF)8++9t2ZJf?NYOZ>7(lVVrrk$FckY@fp zG4)HGefiUBO4;qEpZNSoI{W#{YD)M0rXRm!na-8*mWtbWK<7$pq^1sjL+36YtHw6Y zq;p5*QAvOI(7AUMS3`5QGyUL)pX=OTOj60y%9ws|qntYT<5ep8$0ep8^q`~8^W0)J zGxIpp4{k7C=b1KHC11RS{-hdwuba-ZdyPttzoPT(X{Cl{N!EFe|D%%rj5Yn(svqmT zBb%zJF_Aj&!0ak+ZCjo1P`n!d_DG%YXgRap1=rP9vLB}3xlb3od`(R$*UR*i-grqD zDlkh;PV8fPIUa?|o>f!If1y6Sb4pFwb6kCR?0ps2>ZJMi){+@3E?|K{IE z)y8WlRNS3?rk_}1tJ>aqj7k{MRBdn9RVBXGUhV2xSH)&kYFGbmYSxw=YWIha)X@2L zO+VyCrFQ?Q)$Hb{Oh0&56Sb$~4K;i7FQy-?hNwMPtEt)FY%~4f1yp~>sjN9E(xtc@c~Kkj}7wJ-6WN*tL>?Hg5ICG@|l(%!tP zCVJMYw3&U(b|1Q&tYkl=pB!649iCWC#qC{W`YDyNs>A1}tGG5zO)tmeNaPN6ynA=m zVdO1!{AOR(p?st|5kJWM`>QLNRL6!z)Cn99>A%|ei|RCNkovmXccwq~Oi9&u%2IW5 zYmDlP-*x)vmuleV81;FP1T`@2k~&*Z7|IUez+PU-UA_f^+Qk9GMrS5%h^d3E_EmCV1( z9rdfO_loKAUqzX|+@>z-h0?ur`5UuMU-r&ZYCx4gb%jlp)d2jRV5NG;)UeKbb(w*m zt6>8g>#F_Ns1e>TbyR~TrZ06PNsSmiLRZ}qXZljRYpPeejMh~zjWd0zwS&~i8MSrQ zhc!%JYS%tBYWEa;9-&6<&96&c@1;gB`&3um+(eCDzClOTyQ{|JTB@tY{A&6#{mQDb z|C^^P)pf1A;nG%J_Szja;c-c`-3h-}(6S$<|NNYqI;REpZ(5*_JglbP z?S}oo6X({=yRLUFVh7V z4bd%nWYWY^QA z(a+=WJ!HGvtQn+bKTKc#W!>glVeDT&(--SCO1CW zysV48y;SR3n*#qHR7V%PFjMPc>rAg&ey599EvEGhkLerFo~cW{lAwJpXX#SIf6~q= zM@KzO(2YDDbkw7Fb<@A^>F9S`>UyW!2KpH_baeV{-K^Cm)7R^?Q%65c)y*bfHGMtx zy)NBsjc&GZhw1Be(z^8gark^H`v2*AiMMs>qjhz&=hvbCN7p;GRG0qcFWvN!&-4u+ z;o4nRUpvQh>oRk;YG0GSx?FL;Zk+gbD{k1U_3&(_S1X^_ z70>##t{rQ7IUW^n?bA)KpH-(nNz~1rS+7p7xsUC6$^5(Nj#ld1s!!@>yB?Un>5`i2 z+k>Tbvr|!~Z*sPbI@fTcZoaU$I#+juZdrV^y4b3%ey;O$b+OZ2-P*TZ{kRhM%4+vb zuP*daKc1eUThA_Odi7xo^-~K+xAq@1y;?F`{dA$AZvD+*)2j_%t4pz4@p%t*>9z4% zoiC{_T~5}mXP#G=uKcBS)lTZ?D15H|G5vGxJ?fXKn{>;1Mlon!f4H9P0MNb-LMM0Qs5fU0d((4>Apr5ICOa7hKXInKr{?{*zp11Xm9yh17==3LBUe#TW7ce^JyJqU% zXNgAR$4A3&{u$s-Qrd&tS&hzdc|>}*L4!o6B`wUE9-GqK==RQ?^a#=XYm$oE(W246pteQ4Ba;wqUSJ`LLs>_6n=@W)`GhWlXE3H?YDM~ zbibp1(diwJ`gOjo(MG@exQ|-)>q|zDf3}Sp`qyRA+RPub!RXG-&*(h!%rR8Aaem$T z(>tDMXXiUi<1Sq0ms$JR>}t#e+8wZ}QIFS|AiPw%^YoBE@bIc{kWG8NG=3HgMlJ;+-psOPQy zR*y^BV*F25EUUZxbinACL+_~jIdTVdwF_y#*PLf`jw9>SyG_U=IxT71?ey4Xr;NTk z=WcqxYOfhj%#br_4?4N?j2s%&W3RPNTU5A;@pL-=b9&we3(eTuBZsE<&%9r>BCW}z z$FBFME#9|OJi70V7t$VJsvj)NYT zcezT*bj^(I+%Lb*GvtiuwBMYlf3LA~!*sqy#*;oa$Lng@#{U^lpCu21xnh3K?Rs2X z7UAhn4&9`?>>p-y%!%FVo;@#;AN~&Hlbl#<-P$~D=1IDknjSmd9NV<^y(@+0hc$J~ zJSIN`)=T=>pAMug(vuADbhLYVUMEWQo)f#DvN=H;-oji?j+v)V! zntzDaxjYTiyKer)=$NEc!8LBy^}=z6=RDa z+cPord&!f6&On|?H`j1rZR$>!=BDS3>TUeyI$Ygf zbl`fsGclk?97&IH^{khE`}g={{WQJn`oMmf9Qf6T;+JFmQ9{0vMnCiFb(_Q0%(@eT z*PA&$Ht+S=q3di3T(>6g^~#X35fNGD;YUp)13zk^^SJ-6jo#~O_Asx5&m&#W)95q( zhd-Q$`7;=o*&SO0eHK^qob0KN&$IrAKb(hoU5tCe9n14De-@u-b3N72Xa5g>I1lrB z7?;BxTNQmySM!|gse;dQ{f9rChk1RBd(s_S8GUY7^PJ&4%o|`_9(Qad^m$#)bB6OU zZ-{aE+_4qW=XW*F8P3DJ5ylm8$5udJ(A7L=I1ls27+1(0TOR#WuI4$zd6+AVE9{Of zhrWobdCqVi<{IOQ{>MDbefYeX>nV%AxU2d1`oR9n!`y+V1VUO1L`kC}B6v>rG{@(q zTo3!hd6++kaZ&ErX6U0`&2xtHFmHl!rQNYj(U);G&&i&y_+0i!S~r9oBWW)n zf{^nqjs4*~%)4WZTyxSoBjh@k#&d@AFzX>Ad550J)lhVwA*i!pLuHJJ=W71F z;XKR-Vw~fS9ghAvSM!|g8HUd#M@VCTI1lqd7}L~@jEESDzL~3e&Tt;)gE6kTJ9Y?q z$*0nIPWB|=Gua<$QxS5Eq)kJ}xseu+kn=5#{oy>!6EQ}vIcaeSSsT)L&Tt;)(=kTY zlC&uZS)bB)&Tt;)GcZPSgtRFLI}h_DaLF~&CL<(&Nt=SO{%{`V$?!{_mG&k=a| zlRcC0ncOF&u|J%L`Am$F`;fGW2)UO?<2l25n9sr(xqnD|10nYSX*_2*5A)d=BliYr z6A+T$rSY8MJj~}{jO1%+;}Mc`rSY8MJj~}}jO1BquOlQ^O5-`hd6>V9F)=a_?KOnt zIB7g*I1lp?7}MX344sGhEBO2+*At6=z<>C|d6TLscT3|rSK;6PMvkd8o`?Bb zd?x2l+ERp^Z)xlg=VAUX#>llU?Ja~{>(Y2m_AJ3?vaY1DKb(j8I*gIEEp0JE@`W^> zGn|L{dl(}*OWGoY2b2ZNy&cplz zjFWq(v;~L+qaq@B&Tt;)8!&FFJ9a+$X|Cou!+Ds0h;fPkF%R>N_iTd z_9;Tvr!<~3oQL^wjFB86jpt#00-s5)k@g8f@|QIBhx0K18e=5SN;`s(+%1jgWY1xI zCie+x><{N*eiCEkJ|yiBLhdEfc+PMh=BF@bl?+7t7$NrnX*_2*5A$y@M(z#L4k9GK zOXE4id6=KZn0L*{hzLLWb*|<)!+Ds0i*b@?rDY%_S4!hK!+DtRz?k)BBwkgcmmDW8 z17YV3=V87Re#vXncpm1v@R{T_X=w<_P14vO&cl2+#%wYpBO(r<-|T9hlRf+Kx#S3G z><{N*z6WC@??~H+NHr=Vg69n9VZImRwz*?JLciVBJSTf@;d42@(rzQj*jD(%2u)!~6lp$TcVJ8X`jk8qdj|tN2XTl{EH;^DzG%V`ObhyMmB>A&ut@ z=VAU3V#&d@A zF#ii<3B(s<5r9_HU+%ok>4M8r?%<(@5#=M3jz{yoOXeOemN!~B2vOzy$b zeniNe~GGZ=Tu9eW=AH?F>b-p(1$ z!~87#r`@sV(0}V{o|8PDZ1`M`FPbMie#mh|^W?w}ITmQ1C-6hI6)nUc&ci$>2FdoJ zd9vb%{BE?6Im3CF=fWV_A2d%E{E+=Y3z;*VhxwBjbU{Y`pLv+)#)oqL&^(#(L(Vr^ z$nOp3VV(zrvHZ=B!_3->fG3cQg8sRB{{ts94oZ&poi(%ZK z?%3k!|8h0YNgh+@m;I3@Ygx{XG+B>wZlp;*k!whr^ zyG8Sy>_MJ4_lf`O59eWyHE8ZbG8TE>+=oQ-oZ&pou}(d5ZlocHd*pme<2l25m}8xK z9izb3DV2hHRrBcO54Obh2>j6@tom2%#m+B__t|M(2{?p@toxGfSdP+axAgU z=Dnq8{NA9pT+UTF@B~C8bXn5OD}cu#c*@K+GX5gtXFxdT25 zA^F}%nt2oOF$m-c&vT@iHv=DwkR05UwB?dhTY!&4h;B~Wa>#d0Mg6{gC`>@z%z(6bL_Lpd&oVW zDAGfr*CXWk4@bWNA;)j33Tfu@d*pZ2hG#Kp=1all zcjtlUEz->22AA!~3yH3F9p66{3V3w z9i%Of0^bcj5D^W%i!}4S;IbX1;n_o)`9APrh%)eeM4I^l@ZpHE@a!keJRMy2zZ^Vi zq?!A{2P2+^CxbNekHH5aD!_A)H1osY0}vJAIYioW5BMkG{Scy$kha_l{uy{*L?ra5 zq?vyX-UlK1@F;2KUxN2S)PUy;(#*dC?}5ky&oR=>Pk_IG$O_MK(#%hScSSq_&)1}x ze*@kHkqw?xq?vyU-U%W3@HA=5bAW#j-X0Bs^zG zGd~aB5|JC8bEKJH1b-eO`S1d1=0AbALP$RRku>w4!P_7tA6_EO{4#huM1FXFA@Qw)4*GO9~`S2!qXT(#`H%K$T1>Ox&7@l8AGye^|JE90Yw@EX< z3*HkU`S1>D=J&ySBZ|Ruk2Le&!Cyp3K72r$c`A4eq69o!N&kU=V?QG5q5lhkV-ryy z{hy>QZvgf;0_Q>g&fD{dH1mJJ^TN{z{bSO^y^;%XeaYW>WBLE9nM*E+!iQL=Uda)- zu8n4%860au{^r}8i8OOr!&ravH{V`a^HwtlGw-LCsvQV|*le!7JCj)y(A@m6Q2AJaSE2&AbFS z&XeQ?uUxNITizPH6gbYGJ+tH1jIpa-KTDQ<*gLYT$C7I>S?yH1itZ*iX5yc&kIp zITOviCb*oxuHa9TW?mZ{=TCB(w-#yU&w%4R$-U59hcxqN!Ev7Cdz`l}Y37nsaQ@`E z#VfhSYUYwta2-hA^h&O=nt5YzTu*ZU_DX)Snz;tY^(VR2i@Xrj#65q2<2p8Z@8Q4N z>wx(X9*o6WmHcG%bEGZD_3g#_lw2s!E#9W2nPXi^PL<~tFV<>MGsl{dXR(OP@L-Jv zHFK;Dc}_Pu5bGzXnPWYe|D%)@^I-i1HFI3+=Kn(>$9b_ff|@z5WAp#2vcZGvKB$@F z8kK#L=N2!n>7cee2RN=jxh~|n#fxh+s4d6Z^Wxf)cM0;`;>EQX)XZ_db9rv@zDSyRKX9ybd2aE>kY@f8IM%s5 zw|M)LWs+2&yaPyEUJ!gRIM%;Bw|EDUwjAroF6c9tYk6f$P;fg*5X7@MZ{Huikjl%%_1jK|Bl3RMO0+gFlC;08b)m=Ca>D z1g>eX^b(?z(Bu4=95@p_t_!1+Nn4I}=A8|WYfzq9y|YL&p9_v_S-#78=a6PT9~|pO zo@>4HNHbpuo)?h?o&}_tF9Oev=nGE@Y3577b0K2jSxlPwQgGxd`5xBV z@+k0+!Al@ULmwo~{4jVF0{Po}h&1z0z)K@uh35!q=AVI=L6n8(Q_{>o2aiT{hvz71 z=3jzipQI+|{em>}ufR(p#=&!pH1i~I$$PQz%piRNTIPKX{3LoA|2p*7q?vyMF7u9u z=M-tnyMliUF7x7^<2_B9`S;*5{tbA(BhCB=a2a0(p8t_%eimHjmE(MdH1qS|vVC%# z&yi++5nT3Dj`Ic5%zpxx<1!JRA4xO+8T>e+9z2&wGrtTj=dV6IzmR5r6ns`UxeodY38@U<@(M7&#$DJ{{}AWBr80(Ni)9-?nlJHbB8qZ z``{Ufe(>BQ&HQ(8S?3Ns4@fir1AHH15 z%{)K&5kv=g@{wj<5M1(UF?b4)X8showg+NrAad{ z2Ywl$;3-R*c?IyF5gMNIq?uO&zl89?Q;{_DD&RjN`omM1wB?E5)xggqL{}wk`2g@5 z;Aas{p{tW-UK9KWL^F7vCe6Gy_;-lr@YEvB{2B1?5x52;>yT#tEV$fnTEJ76H1qo4 zXAmvnL9P#K=C~%z->5$iPXp4-alRuiAh0cwxITi~a$MJuI8Wy9&qd?B2DRn5#v>i@ zpAc=KeWaN;0sjTj4xZ;oGsp2YfA8HM9-NP$W{%@x{+3(TDUNkeGsixgztipr4~|h# zGj9$4E20xT$WuYh9Q$MbzIr-5ZAdf6wwk}4o&gW`EvPL|0>^fkznvD1?G9?olfgTK z-$!(V#x?~t^RD1>zj* .5) { - uv.x = 1.0 - uv.x; - } } - float mixValue = clamp(distance(uv.xy, vec2(0.0)), 0.0, 1.0); - vec4 gradientColorFinal = vec4(mix(gradientColor1, gradientColor2, mixValue), 1.0); + uv.x = 1.0 - uv.x; - float modelNormalSpec = normalSpec, modelSpec1 = 0.0, modelSpec2 = 0.05; - - float darken = 1. - length(modelViewVertex - vec3(30., -75., 50.)) / 200.; - - if (border > 0.) { - modelNormalSpec += border; - modelSpec1 += border; - modelSpec2 += border; - } - - - vec3 angleW = normalize(viewDirectionW + vLightPosition2); - float specComp2 = max(0., dot(finalNormal, angleW)); - specComp2 = pow(specComp2, max(1., 128.)) * modelSpec1; - - angleW = normalize(viewDirectionW + vLightPosition4); - float specComp3 = max(0., dot(finalNormal, angleW)); - specComp3 = pow(specComp3, max(1., 30.)) * modelSpec2; - - angleW = normalize(viewDirectionW + vLightPositionNormal); - float normalSpecComp = max(0., dot(finalNormal, angleW)); - normalSpecComp = pow(normalSpecComp, max(1., 128.)) * modelNormalSpec; - - angleW = normalize(viewDirectionW + vLightPosition2); - float normalSpecComp2 = max(0., dot(finalNormal, angleW)); - normalSpecComp2 = pow(normalSpecComp2, max(1., 128.)) * modelNormalSpec; - - vec4 normalSpecFinal = vec4(normalSpecColor, 0.0) * normalSpecComp2; - vec4 specFinal = vec4(color, 0.0) * (specComp2 + specComp3); - -// float snap = fract((-gl_FragCoord.x / resolution.x + gl_FragCoord.y / resolution.y) / 20.0 + .2 * time) > .9 ? 1. : 0.; - - vec4 fragColor = gradientColorFinal + specFinal; - vec4 backgroundColor = texture2D(u_BackgroundTexture, vec2(gradientPosition.x + (gl_FragCoord.x / resolution.x) * gradientPosition.y, gradientPosition.z + (1.0 - (gl_FragCoord.y / resolution.y)) * gradientPosition.w)); - vec4 color4 = mix(backgroundColor, fragColor, diffuse); - if (night) { - angleW = normalize(viewDirectionW + vLightPosition2); - float normalSpecComp = max(0., dot(finalNormal, angleW)); - normalSpecComp = pow(normalSpecComp, max(1., 128.)); - if (normalSpecComp > .2 && modelIndex != 0) { - color4.rgb += vec3(.5) * max(0., vTextureNormal.x) * normalSpecComp; - } - if (modelIndex == 1) { - color4.rgb *= .9; - } else { - color4.rgb += vec3(1.0) * .17; - } + float diagonal = ((uv.x + uv.y) / 2.0 - .15) / .6; + vec3 baseColor; + if (modelIndex == 0) { + baseColor = mix( + vec3(0.95686, 0.47451, 0.93725), + vec3(0.46274, 0.49411, 0.9960), + diagonal + ); + } else if (modelIndex == 3) { + baseColor = mix( + vec3(0.95686, 0.47451, 0.93725), + vec3(0.46274, 0.49411, 0.9960), + diagonal + ); + baseColor = mix(baseColor, vec3(1.0), .3); + } else if (modelIndex == 1) { + baseColor = mix( + vec3(0.67059, 0.25490, 0.80000), + vec3(0.39608, 0.18824, 0.98039), + diagonal + ); } else { - if (modelIndex == 1) { - if (darken > .5) { - color4.rgb *= vec3(0.78039, 0.77254, 0.95294); - } else { - color4.rgb *= vec3(0.83921, 0.83529, 0.96862); - } - } else { - if (darken > .5) { - color4.rgb *= vec3(.945098, .94117, 1.0); - color4.rgb += vec3(.06) * border; - } + baseColor = mix( + vec3(0.91373, 0.62353, 0.99608), + vec3(0.67451, 0.58824, 1.00000), + clamp((uv.y - .2) / .6, 0.0, 1.0) + ); + + baseColor = mix(baseColor, vec3(1.0), .1 + .45 * texture2D(u_Texture, vUV).a); + if (night) { + baseColor = mix(baseColor, vec3(.0), .06); } } - gl_FragColor = color4 * f_alpha; + + vec3 pos = modelViewVertex / 100.0 + .5; + vec3 norm = normalize(vec3(world * vec4(vNormal, 0.0))); + + vec3 flecksLightPos = vec3(.5, .5, .5); + vec3 flecksLightDir = normalize(flecksLightPos - pos); + vec3 flecksReflectDir = reflect(-flecksLightDir, norm); + float flecksSpec = pow(max(dot(normalize(vec3(0.0) - pos), flecksReflectDir), 0.0), 8.0); + vec3 flecksNormal = normalize(texture2D(u_NormalMap, uv * 1.3 + vec2(.02, .06) * time).xyz * 2.0 - 1.0); + float flecks = max(flecksNormal.x, flecksNormal.y) * flecksSpec; + norm += flecksSpec * flecksNormal; + norm = normalize(norm); + + vec3 lightPos = vec3(-3., -3., 20.); + vec3 lightDir = normalize(lightPos - pos); + float diffuse = max(dot(norm, lightDir), 0.0); + + float spec = 0.0; + + lightPos = vec3(-3., -3., .5); + spec += 2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0); + + lightPos = vec3(-3., .5, 30.); + spec += (modelIndex == 1 ? 1.5 : 0.5) * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 32.0); + +// lightPos = vec3(3., .5, .5); +// spec += pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 32.0); + + if (modelIndex != 0) { + spec *= .25; + } + + vec3 color = baseColor; + color *= .94 + .22 * diffuse; + color = mix(color, vec3(1.0), spec); +// color = mix(color, vec3(1.0), 0.35 * flecks); + + gl_FragColor = vec4(color, 1.0); } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 19a63c86b..a8e206260 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -207,7 +207,13 @@ import java.util.Hashtable; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; @@ -265,9 +271,11 @@ public class AndroidUtilities { public static final RectF rectTmp = new RectF(); public static final Rect rectTmp2 = new Rect(); + public static final int[] pointTmp2 = new int[2]; public static Pattern WEB_URL = null; public static Pattern BAD_CHARS_PATTERN = null; + public static Pattern LONG_BAD_CHARS_PATTERN = null; public static Pattern BAD_CHARS_MESSAGE_PATTERN = null; public static Pattern BAD_CHARS_MESSAGE_LONG_PATTERN = null; private static Pattern singleTagPatter = null; @@ -276,6 +284,7 @@ public class AndroidUtilities { try { final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; BAD_CHARS_PATTERN = Pattern.compile("[\u2500-\u25ff]"); + LONG_BAD_CHARS_PATTERN = Pattern.compile("[\u4e00-\u9fff]"); BAD_CHARS_MESSAGE_LONG_PATTERN = Pattern.compile("[\u0300-\u036f\u2066-\u2067]+"); BAD_CHARS_MESSAGE_PATTERN = Pattern.compile("[\u2066-\u2067]+"); final Pattern IP_ADDRESS = Pattern.compile( @@ -565,9 +574,13 @@ public class AndroidUtilities { } public static CharSequence replaceArrows(CharSequence text, boolean link) { + return replaceArrows(text, link, dp(8f / 3f), 0); + } + + public static CharSequence replaceArrows(CharSequence text, boolean link, float translateX, float translateY) { ColoredImageSpan span = new ColoredImageSpan(R.drawable.msg_mini_forumarrow, DynamicDrawableSpan.ALIGN_BOTTOM); span.setScale(.88f, .88f); - span.translate(-dp(8f / 3f), 0); + span.translate(-translateX, translateY); span.spaceScaleX = .8f; if (link) { span.useLinkPaintColor = link; @@ -581,6 +594,23 @@ public class AndroidUtilities { rightArrow.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); text = AndroidUtilities.replaceMultipleCharSequence(">", text, rightArrow); + span = new ColoredImageSpan(R.drawable.msg_mini_forumarrow, DynamicDrawableSpan.ALIGN_BOTTOM); + span.setScale(.88f, .88f); + span.translate(translateX, translateY); + span.rotate(180f); + span.spaceScaleX = .8f; + if (link) { + span.useLinkPaintColor = link; + } + +// SpannableString leftArrow = new SpannableString("< "); +// leftArrow.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); +// text = AndroidUtilities.replaceMultipleCharSequence("< ", text, leftArrow); + + SpannableString leftArrow = new SpannableString("<"); + leftArrow.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text = AndroidUtilities.replaceMultipleCharSequence("<", text, leftArrow); + return text; } @@ -938,14 +968,56 @@ public class AndroidUtilities { return true; }; + @Deprecated // use addLinksSafe public static boolean addLinks(Spannable text, int mask) { return addLinks(text, mask, false); } + @Deprecated // use addLinksSafe public static boolean addLinks(Spannable text, int mask, boolean internalOnly) { return addLinks(text, mask, internalOnly, true); } + public static boolean addLinksSafe(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) { + SpannableStringBuilder newText = new SpannableStringBuilder(text); + ExecutorService executor = Executors.newSingleThreadExecutor(); + Callable task = () -> { + try { + return addLinks(newText, mask, internalOnly, removeOldReplacements); + } catch (Exception e) { + FileLog.e(e); + return false; + } + }; + boolean success = false; + Future future = null; + try { + future = executor.submit(task); + success = future.get(200, TimeUnit.MILLISECONDS); + } catch (TimeoutException ex) { + if (future != null) { + future.cancel(true); + } + } catch (Exception ex) { + FileLog.e(ex); + } finally { + executor.shutdownNow(); + } + if (success && text != null) { + URLSpan[] oldSpans = text.getSpans(0, text.length(), URLSpan.class); + for (int i = 0; i < oldSpans.length; ++i) { + text.removeSpan(oldSpans[i]); + } + URLSpan[] newSpans = newText.getSpans(0, newText.length(), URLSpan.class); + for (int i = 0; i < newSpans.length; ++i) { + text.setSpan(newSpans[i], newText.getSpanStart(newSpans[i]), newText.getSpanEnd(newSpans[i]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return true; + } + return false; + } + + @Deprecated // use addLinksSafe public static boolean addLinks(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) { if (text == null || containsUnsupportedCharacters(text.toString()) || mask == 0) { return false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java index 92e45c323..2da02d751 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java @@ -51,11 +51,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { debugCanceledCount++; if (!debugReportSend && debugCanceledCount > 200) { debugReportSend = true; - if (BuildVars.DEBUG_PRIVATE_VERSION) { - throw new RuntimeException("infinity stream reading!!!"); - } else { - FileLog.e(new RuntimeException("infinity stream reading!!!")); - } + FileLog.e(new RuntimeException("infinity stream reading!!!")); } return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java index e1a0f78a0..6f17d2388 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java @@ -120,4 +120,9 @@ public class AuthTokensHelper { preferences.edit().putString("log_out_token_" + count, Utilities.bytesToHex(data.toByteArray())).putInt("count", count + 1).apply(); BackupAgent.requestBackup(ApplicationLoader.applicationContext); } + + public static void clearLogInTokens() { + ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens_login", Context.MODE_PRIVATE).edit().clear().apply(); + ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE).edit().clear().apply(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index f7bc863d7..51212a0de 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -1592,6 +1592,51 @@ public class ChatObject { return chat != null && (getBannedRight(chat.banned_rights, action) || getBannedRight(chat.default_banned_rights, action)); } + public static boolean canUserDoAdminAction(TLRPC.TL_chatAdminRights admin_rights, int action) { + if (admin_rights != null) { + boolean value; + switch (action) { + case ACTION_PIN: + value = admin_rights.pin_messages; + break; + case ACTION_MANAGE_TOPICS: + value = admin_rights.manage_topics; + break; + case ACTION_CHANGE_INFO: + value = admin_rights.change_info; + break; + case ACTION_INVITE: + value = admin_rights.invite_users; + break; + case ACTION_ADD_ADMINS: + value = admin_rights.add_admins; + break; + case ACTION_POST: + value = admin_rights.post_messages; + break; + case ACTION_EDIT_MESSAGES: + value = admin_rights.edit_messages; + break; + case ACTION_DELETE_MESSAGES: + value = admin_rights.delete_messages; + break; + case ACTION_BLOCK_USERS: + value = admin_rights.ban_users; + break; + case ACTION_MANAGE_CALLS: + value = admin_rights.manage_call; + break; + default: + value = false; + break; + } + if (value) { + return true; + } + } + return false; + } + public static boolean canUserDoAdminAction(TLRPC.Chat chat, int action) { if (chat == null) { return false; @@ -1643,6 +1688,43 @@ public class ChatObject { return false; } + public static boolean canUserDoAction(TLRPC.Chat chat, TLRPC.ChannelParticipant participant, int action) { + if (chat == null) { + return true; + } + if (participant == null) { + return false; + } + if (canUserDoAdminAction(participant.admin_rights, action)) { + return true; + } + if (getBannedRight(participant.banned_rights, action)) { + return false; + } + if (isBannableAction(action)) { + if (participant.admin_rights != null && !isAdminAction(action)) { + return true; + } + if (chat.default_banned_rights == null && ( + chat instanceof TLRPC.TL_chat_layer92 || + chat instanceof TLRPC.TL_chat_old || + chat instanceof TLRPC.TL_chat_old2 || + chat instanceof TLRPC.TL_channel_layer92 || + chat instanceof TLRPC.TL_channel_layer77 || + chat instanceof TLRPC.TL_channel_layer72 || + chat instanceof TLRPC.TL_channel_layer67 || + chat instanceof TLRPC.TL_channel_layer48 || + chat instanceof TLRPC.TL_channel_old)) { + return true; + } + if (chat.default_banned_rights == null || getBannedRight(chat.default_banned_rights, action)) { + return false; + } + return true; + } + return false; + } + public static boolean canUserDoAction(TLRPC.Chat chat, int action) { if (chat == null) { return true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java index fc12553cd..875e2beaa 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java @@ -233,9 +233,9 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; if (Build.VERSION.SDK_INT >= 18) { - innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question.text); } else { - innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question.text); } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { @@ -297,7 +297,7 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { } else { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; - messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; + messageString = "\uD83D\uDCCA " + mediaPoll.poll.question.text; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; } else if (message.type == MessageObject.TYPE_MUSIC) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index f0d9c0584..70db7db49 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1497,6 +1497,13 @@ public class DatabaseMigrationHelper { version = 152; } + if (version == 152) { + database.executeFast("ALTER TABLE profile_stories ADD COLUMN pin INTEGER default 0;").stepThis().dispose(); + + database.executeFast("PRAGMA user_version = 153").stepThis().dispose(); + version = 153; + } + return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java index 189740c2e..9110e17fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java @@ -45,25 +45,40 @@ public class DocumentObject { } } + public static boolean containsPhotoSizeType(ArrayList sizes, String type) { + if (type == null) + return false; + for (int a = 0, N = sizes.size(); a < N; a++) { + TLRPC.PhotoSize photoSize = sizes.get(a); + if (type.equalsIgnoreCase(photoSize.type)) + return true; + } + return false; + } + public static SvgHelper.SvgDrawable getSvgThumb(ArrayList sizes, int colorKey, float alpha) { - int w = 0; - int h = 0; + return getSvgThumb(sizes, colorKey, alpha, false); + } + + public static SvgHelper.SvgDrawable getSvgThumb(ArrayList sizes, int colorKey, float alpha, boolean usePhotoSize) { + int w = 512; + int h = 512; TLRPC.TL_photoPathSize photoPathSize = null; for (int a = 0, N = sizes.size(); a < N; a++) { TLRPC.PhotoSize photoSize = sizes.get(a); if (photoSize instanceof TLRPC.TL_photoPathSize) { photoPathSize = (TLRPC.TL_photoPathSize) photoSize; - } else if (photoSize instanceof TLRPC.TL_photoSize) { + } else if (photoSize instanceof TLRPC.TL_photoSize && usePhotoSize) { w = photoSize.w; h = photoSize.h; } - if (photoPathSize != null && w != 0 && h != 0) { - SvgHelper.SvgDrawable pathThumb = SvgHelper.getDrawableByPath(photoPathSize.svgPath, w, h); - if (pathThumb != null) { - pathThumb.setupGradient(colorKey, alpha, false); - } - return pathThumb; + } + if (photoPathSize != null && w != 0 && h != 0) { + SvgHelper.SvgDrawable pathThumb = SvgHelper.getDrawableByPath(photoPathSize.svgPath, w, h); + if (pathThumb != null) { + pathThumb.setupGradient(colorKey, alpha, false); } + return pathThumb; } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index a09ce1f9a..a519ff055 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -38,6 +38,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Locale; +import java.util.Objects; public class Emoji { @@ -796,6 +797,14 @@ public class Emoji { } super.updateDrawState(ds); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EmojiSpan emojiSpan = (EmojiSpan) o; + return Float.compare(scale, emojiSpan.scale) == 0 && size == emojiSpan.size && Objects.equals(emoji, emojiSpan.emoji); + } } public static void addRecentEmoji(String code) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index d5faa892b..e2c5f7ea2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -867,6 +867,9 @@ public class FileLoadOperation { startDownloadRequest(-1); nextPartWasPreloaded = false; } + if (notLoadedBytesRanges != null) { + notifyStreamListeners(); + } }); } else if (alreadyStarted) { Utilities.stageQueue.postRunnable(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 44a0fde3d..33c3dbea3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -91,7 +91,7 @@ public class FileRefController extends BaseController { } else if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; long channelId = messageObject.getChannelId(); - return "message" + messageObject.getRealId() + "_" + channelId + "_" + messageObject.scheduled; + return "message" + messageObject.getRealId() + "_" + channelId + "_" + messageObject.scheduled + "_" + messageObject.getQuickReplyId(); } else if (parentObject instanceof TLRPC.Message) { TLRPC.Message message = (TLRPC.Message) parentObject; long channelId = message.peer_id != null ? message.peer_id.channel_id : 0; @@ -210,6 +210,11 @@ public class FileRefController extends BaseController { locationKey = "file_" + req.id.id; location = new TLRPC.TL_inputDocumentFileLocation(); location.id = req.id.id; + } else if (args[0] instanceof TLRPC.TL_stickers_addStickerToSet) { + TLRPC.TL_stickers_addStickerToSet req = (TLRPC.TL_stickers_addStickerToSet) args[0]; + locationKey = "file_" + req.sticker.document.id; + location = new TLRPC.TL_inputDocumentFileLocation(); + location.id = req.sticker.document.id; } else if (args[0] instanceof TLRPC.TL_messages_faveSticker) { TLRPC.TL_messages_faveSticker req = (TLRPC.TL_messages_faveSticker) args[0]; locationKey = "file_" + req.id.id; @@ -390,6 +395,12 @@ public class FileRefController extends BaseController { req.peer = getMessagesController().getInputPeer(messageObject.getDialogId()); req.id.add(messageObject.getRealId()); getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); + } else if (messageObject.isQuickReply()) { + TLRPC.TL_messages_getQuickReplyMessages req = new TLRPC.TL_messages_getQuickReplyMessages(); + req.shortcut_id = messageObject.getQuickReplyId(); + req.flags |= 1; + req.id.add(messageObject.getRealId()); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (channelId != 0) { TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); req.channel = getMessagesController().getInputChannel(channelId); @@ -638,6 +649,15 @@ public class FileRefController extends BaseController { req.id.file_reference = file_reference; getConnectionsManager().sendRequest(req, (response, error) -> { + }); + } else if (requester.args[0] instanceof TLRPC.TL_stickers_addStickerToSet) { + TLRPC.TL_stickers_addStickerToSet req = (TLRPC.TL_stickers_addStickerToSet) requester.args[0]; + if (fromCache && isSameReference(req.sticker.document.file_reference, file_reference)) { + return false; + } + req.sticker.document.file_reference = file_reference; + getConnectionsManager().sendRequest(req, (response, error) -> { + }); } else if (requester.args[0] instanceof TLRPC.TL_messages_faveSticker) { TLRPC.TL_messages_faveSticker req = (TLRPC.TL_messages_faveSticker) requester.args[0]; @@ -717,6 +737,9 @@ public class FileRefController extends BaseController { } else if (args[0] instanceof TLRPC.TL_messages_saveRecentSticker) { TLRPC.TL_messages_saveRecentSticker req = (TLRPC.TL_messages_saveRecentSticker) args[0]; //do nothing + } else if (args[0] instanceof TLRPC.TL_stickers_addStickerToSet) { + TLRPC.TL_stickers_addStickerToSet req = (TLRPC.TL_stickers_addStickerToSet) args[0]; + //do nothing } else if (args[0] instanceof TLRPC.TL_messages_faveSticker) { TLRPC.TL_messages_faveSticker req = (TLRPC.TL_messages_faveSticker) args[0]; //do nothing @@ -779,11 +802,10 @@ public class FileRefController extends BaseController { continue; } if (error != null && BuildVars.LOGS_ENABLED) { - if (requester.args[1] instanceof FileLoadOperation) { + if (requester.args.length > 1 && requester.args[1] instanceof FileLoadOperation) { FileLoadOperation operation = (FileLoadOperation) requester.args[1]; FileLog.e("debug_loading: " + operation.getCacheFileFinal().getName() + " can't update file reference: " + error.code + " " + error.text); } - } if (requester.location instanceof TLRPC.TL_inputFileLocation || requester.location instanceof TLRPC.TL_inputPeerPhotoFileLocation) { locationReplacement = new TLRPC.InputFileLocation[1]; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 12cc0c901..92b0a94b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -3584,6 +3584,8 @@ public class ImageLoader { } url = url + docExt; saveImageToCache = !MessageObject.isVideoDocument(object.document) && !MessageObject.isGifDocument(object.document) && !MessageObject.isRoundVideoDocument(object.document) && !MessageObject.canPreviewDocument(object.document); + } else if (parentObject instanceof TLRPC.StickerSet) { + url = url + "." + ext; } if (a == 0) { imageKey = key; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java index a3cd2c707..e93a13988 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java @@ -297,6 +297,22 @@ public class ImageLocation { return imageLocation; } + public static ImageLocation getForStickerSet(TLRPC.StickerSet set) { + if (set == null) return null; + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(set.thumbs, 90); + if (photoSize == null) return null; + TLRPC.InputStickerSet inputStickerSet; + if (set.access_hash != 0) { + inputStickerSet = new TLRPC.TL_inputStickerSetID(); + inputStickerSet.id = set.id; + inputStickerSet.access_hash = set.access_hash; + } else { + inputStickerSet = new TLRPC.TL_inputStickerSetShortName(); + inputStickerSet.short_name = set.short_name; + } + return getForPhoto(photoSize.location, photoSize.size, null, null, null, TYPE_SMALL, photoSize.location.dc_id, inputStickerSet, photoSize.type); + } + private static ImageLocation getForPhoto(TLRPC.FileLocation location, int size, TLRPC.Photo photo, TLRPC.Document document, TLRPC.InputPeer photoPeer, int photoPeerType, int dc_id, TLRPC.InputStickerSet stickerSet, String thumbSize) { if (location == null || photo == null && photoPeer == null && stickerSet == null && document == null) { return null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 61025ff2b..37b9492da 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -1647,6 +1647,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (drawable instanceof SvgHelper.SvgDrawable) { svgDrawable = (SvgHelper.SvgDrawable) drawable; svgDrawable.setParent(this); + } else if (drawable instanceof ClipRoundedDrawable && ((ClipRoundedDrawable) drawable).getDrawable() instanceof SvgHelper.SvgDrawable) { + svgDrawable = (SvgHelper.SvgDrawable) ((ClipRoundedDrawable) drawable).getDrawable(); + svgDrawable.setParent(this); } if (colorFilter != null && drawable != null) { drawable.setColorFilter(colorFilter); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java index be0e39190..05bfb2f15 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java @@ -577,7 +577,11 @@ public class LocationController extends BaseController implements NotificationCe info.lastSentProximityMeters = info.proximityMeters = message.media.proximity_notification_radius; info.account = currentAccount; info.messageObject = new MessageObject(currentAccount, message, false, false); - info.stopTime = getConnectionsManager().getCurrentTime() + info.period; + if (info.period == 0x7FFFFFFF) { + info.stopTime = Integer.MAX_VALUE; + } else { + info.stopTime = getConnectionsManager().getCurrentTime() + info.period; + } final SharingLocationInfo old = sharingLocationsMap.get(info.did); sharingLocationsMap.put(info.did, info); if (old != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index e8bc153a5..0e22a185c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -455,6 +455,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, public boolean isMuted; public boolean canDeleteAfter; public boolean hasSpoiler; + public String emoji; public boolean isChatPreviewSpoilerRevealed; public boolean isAttachSpoilerRevealed; @@ -527,6 +528,39 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, hasSpoiler = false; super.reset(); } + + public void deleteAll() { + if (path != null) { + try { + new File(path).delete(); + } catch (Exception ignore) {} + } + if (fullPaintPath != null) { + try { + new File(fullPaintPath).delete(); + } catch (Exception ignore) {} + } + if (paintPath != null) { + try { + new File(paintPath).delete(); + } catch (Exception ignore) {} + } + if (imagePath != null) { + try { + new File(imagePath).delete(); + } catch (Exception ignore) {} + } + if (filterPath != null) { + try { + new File(filterPath).delete(); + } catch (Exception ignore) {} + } + if (croppedPaintPath != null) { + try { + new File(croppedPaintPath).delete(); + } catch (Exception ignore) {} + } + } } public static class SearchImage extends MediaEditState { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index c16094d77..0067baacb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -1177,7 +1177,24 @@ public class MediaDataController extends BaseController { } public TLRPC.TL_messages_stickerSet getStickerSetByName(String name) { - return stickerSetsByName.get(name); + if (name == null) return null; + return stickerSetsByName.get(name.toLowerCase()); + } + + public void findStickerSetByNameInCache(String name, Utilities.Callback whenFound) { + if (whenFound == null) + return; + if (name == null) { + whenFound.run(null); + return; + } + getMessagesStorage().getStorageQueue().postRunnable(() -> { + TLRPC.TL_messages_stickerSet cachedSet = getCachedStickerSetInternal(name.toLowerCase(), 0); + AndroidUtilities.runOnUIThread(() -> { + putStickerSet(cachedSet, false); + whenFound.run(cachedSet); + }); + }); } public TLRPC.TL_messages_stickerSet getStickerSetByEmojiOrName(String emoji) { @@ -1363,6 +1380,42 @@ public class MediaDataController extends BaseController { return null; } + public void putStickerSet(TLRPC.TL_messages_stickerSet set) { + putStickerSet(set, true); + } + + public void putStickerSet(TLRPC.TL_messages_stickerSet set, boolean notify) { + if (set == null || set.set == null) return; + stickerSetsById.put(set.set.id, set); + if (!TextUtils.isEmpty(set.set.short_name)) { + stickerSetsByName.put(set.set.short_name.toLowerCase(), set); + } + for (int i = 0; i < stickerSets.length; ++i) { + ArrayList sets = stickerSets[i]; + if (sets != null) { + for (int j = 0; j < sets.size(); ++j) { + TLRPC.TL_messages_stickerSet setB = sets.get(j); + if (setB != null && setB.set != null && setB.set.id == set.set.id) { + sets.set(j, set); + } + } + } + } + if (groupStickerSets.containsKey(set.set.id)) { + groupStickerSets.put(set.set.id, set); + } + saveStickerSetIntoCache(set); + int type = TYPE_IMAGE; + if (set.set.masks) { + type = TYPE_MASK; + } else if (set.set.emojis) { + type = TYPE_EMOJIPACKS; + } + if (notify) { + getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true); + } + } + private boolean cleanedupStickerSetCache; private void cleanupStickerSetCache() { if (cleanedupStickerSetCache) { @@ -2071,8 +2124,11 @@ public class MediaDataController extends BaseController { } public void storeTempStickerSet(TLRPC.TL_messages_stickerSet set) { + if (set == null || set.set == null) return; stickerSetsById.put(set.set.id, set); - stickerSetsByName.put(set.set.short_name, set); + if (set.set.short_name != null) { + stickerSetsByName.put(set.set.short_name.toLowerCase(), set); + } } public void addNewStickerSet(TLRPC.TL_messages_stickerSet set) { @@ -3236,7 +3292,9 @@ public class MediaDataController extends BaseController { stickerSets[type].add(finalCurrentIndex, messages_stickerSet); stickerSetsById.put(stickerSet.id, messages_stickerSet); installedStickerSetsById.put(stickerSet.id, messages_stickerSet); - stickerSetsByName.put(stickerSet.short_name, messages_stickerSet); + if (stickerSet.short_name != null) { + stickerSetsByName.put(stickerSet.short_name.toLowerCase(), messages_stickerSet); + } removingStickerSetsUndos.remove(stickerSet.id); loadHash[type] = calcStickersHash(stickerSets[type]); @@ -5940,7 +5998,7 @@ public class MediaDataController extends BaseController { object.applyTimestampsHighlightForReplyMsg(); object.messageOwner.reply_to = new TLRPC.TL_messageReplyHeader(); object.messageOwner.reply_to.flags |= 16; - object.messageOwner.reply_to.reply_to_msg_id = messageObject.getId(); + object.messageOwner.reply_to.reply_to_msg_id = messageObject.getRealId(); } } } @@ -5974,14 +6032,14 @@ public class MediaDataController extends BaseController { if (messageObject == null) { continue; } - if (!messageObject.isReplyToStory() && messageObject.isReply() && messageObject.getId() > 0) { + if (!messageObject.isReplyToStory() && messageObject.isReply() && messageObject.getRealId() > 0) { if (messageObject.messageOwner.reply_to.reply_to_peer_id != null) { continue; } int reply_to_id = messageObject.messageOwner.reply_to.reply_to_msg_id; for (int j = 0; j < messages.size(); ++j) { if (a == j) continue; - if (messages.get(j) != null && messages.get(j).getId() == reply_to_id) { + if (messages.get(j) != null && messages.get(j).getRealId() == reply_to_id) { messageObject.replyMessageObject = messages.get(j); messageObject.applyTimestampsHighlightForReplyMsg(); if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { @@ -6017,7 +6075,7 @@ public class MediaDataController extends BaseController { long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer); messageObject.messageOwner.media.storyItem = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, messageObject.messageOwner.media.storyItem); } - } else if (messageObject.getId() > 0 && messageObject.isReplyToStory()) { + } else if (messageObject.getRealId() > 0 && messageObject.isReplyToStory()) { if (messageObject.messageOwner.replyStory == null) { long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer); if (messagesWithUnknownStories == null) { @@ -6033,7 +6091,7 @@ public class MediaDataController extends BaseController { long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer); messageObject.messageOwner.replyStory = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, messageObject.messageOwner.replyStory); } - } else if (messageObject.getId() > 0 && messageObject.isReply()) { + } else if (messageObject.getRealId() > 0 && messageObject.isReply()) { int messageId = messageObject.messageOwner.reply_to.reply_to_msg_id; if (messageId == threadMessageId) { continue; @@ -6987,7 +7045,7 @@ public class MediaDataController extends BaseController { } if (spannable instanceof Spannable) { - AndroidUtilities.addLinks((Spannable) spannable, Linkify.WEB_URLS, false, false); + AndroidUtilities.addLinksSafe((Spannable) spannable, Linkify.WEB_URLS, false, false); URLSpan[] spansUrl = spannable.getSpans(0, message[0].length(), URLSpan.class); if (spansUrl != null && spansUrl.length > 0) { if (entities == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 705e12107..210ce9327 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -159,6 +159,7 @@ public class MessageObject { public String customName; public boolean reactionsChanged; public boolean isReactionPush; + public boolean isStoryReactionPush; public boolean isStoryPush, isStoryMentionPush, isStoryPushHidden; public boolean putInDownloadsStore; public boolean isDownloadingFile; @@ -199,22 +200,21 @@ public class MessageObject { public boolean isRestrictedMessage; public long loadedFileSize; public boolean forceExpired; + public long actionDeleteGroupEventId = -1; public boolean isSpoilersRevealed; public boolean isMediaSpoilersRevealed; public boolean isMediaSpoilersRevealedInSharedMedia; public boolean revealingMediaSpoilers; public byte[] sponsoredId; - public int sponsoredChannelPost; - public TLRPC.ChatInvite sponsoredChatInvite; - public String sponsoredChatInviteHash; - public boolean sponsoredShowPeerPhoto; + public String sponsoredTitle, sponsoredUrl; public boolean sponsoredRecommended; + public TLRPC.Photo sponsoredPhoto; public String sponsoredInfo, sponsoredAdditionalInfo; - public TLRPC.TL_sponsoredWebPage sponsoredWebPage; - public TLRPC.BotApp sponsoredBotApp; public String sponsoredButtonText; + public TLRPC.TL_peerColor sponsoredColor; public boolean sponsoredCanReport; + public boolean replyTextEllipsized; public boolean replyTextRevealed; public int overrideLinkColor = -1; @@ -224,8 +224,6 @@ public class MessageObject { public TLRPC.TL_forumTopic replyToForumTopic; // used only for reply message in view all messages - public String botStartParam; - public boolean animateComments; public boolean loadingCancelled; @@ -253,7 +251,7 @@ public class MessageObject { return 0; } - public ArrayList checkedVotes; + public ArrayList checkedVotes; public CharSequence editingMessage; public ArrayList editingMessageEntities; @@ -601,6 +599,7 @@ public class MessageObject { public float currentX; public float currentY; public float timeAlpha; + public float progress; } public static class VCardData { @@ -1471,7 +1470,7 @@ public class MessageObject { backgroundChangeBounds = false; } } - + public boolean contains(int messageId) { if (messages == null) { return false; @@ -1941,6 +1940,7 @@ public class MessageObject { new_participant = action.new_participant; } messageOwner = new TLRPC.TL_message(); + messageOwner.realId = -1; long peerId = MessageObject.getPeerId(prev_participant.peer); TLObject whoUser; if (peerId > 0) { @@ -2008,7 +2008,7 @@ public class MessageObject { } if (o.delete_messages != n.delete_messages) { rights.append('\n').append(n.delete_messages ? '+' : '-').append(' '); - rights.append(LocaleController.getString("EventLogPromotedDeleteMessages", R.string.EventLogPromotedDeleteMessages)); + rights.append(LocaleController.getString(R.string.EventLogPromotedDeleteMessages)); } if (o.add_admins != n.add_admins) { rights.append('\n').append(n.add_admins ? '+' : '-').append(' '); @@ -2043,6 +2043,7 @@ public class MessageObject { } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDefaultBannedRights) { TLRPC.TL_channelAdminLogEventActionDefaultBannedRights bannedRights = (TLRPC.TL_channelAdminLogEventActionDefaultBannedRights) event.action; messageOwner = new TLRPC.TL_message(); + messageOwner.realId = -1; TLRPC.TL_chatBannedRights o = bannedRights.prev_banned_rights; TLRPC.TL_chatBannedRights n = bannedRights.new_banned_rights; @@ -2120,6 +2121,7 @@ public class MessageObject { } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantToggleBan) { TLRPC.TL_channelAdminLogEventActionParticipantToggleBan action = (TLRPC.TL_channelAdminLogEventActionParticipantToggleBan) event.action; messageOwner = new TLRPC.TL_message(); + messageOwner.realId = -1; long peerId = getPeerId(action.prev_participant.peer); TLObject whoUser; if (peerId > 0) { @@ -2306,9 +2308,9 @@ public class MessageObject { } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) { message = ((TLRPC.TL_channelAdminLogEventActionDeleteMessage) event.action).message; if (fromUser != null && fromUser.id == MessagesController.getInstance(currentAccount).telegramAntispamUserId) { - messageText = LocaleController.getString("EventLogDeletedMessages", R.string.EventLogDeletedMessages).replace("un1", UserObject.getUserName(fromUser)); + messageText = LocaleController.getString(R.string.EventLogDeletedMessages).replace("un1", UserObject.getUserName(fromUser)); } else { - messageText = replaceWithLink(LocaleController.getString("EventLogDeletedMessages", R.string.EventLogDeletedMessages), "un1", fromUser); + messageText = replaceWithLink(LocaleController.getString(R.string.EventLogDeletedMessages), "un1", fromUser); } } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeLinkedChat) { long newChatId = ((TLRPC.TL_channelAdminLogEventActionChangeLinkedChat) event.action).new_value; @@ -2990,9 +2992,8 @@ public class MessageObject { message.out = false; message.realId = message.id; message.id = mid[0]++; - message.flags &= ~TLRPC.MESSAGE_FLAG_REPLY; - message.reply_to = null; message.flags = message.flags & ~TLRPC.MESSAGE_FLAG_EDITED; + message.dialog_id = -chat.id; MessageObject messageObject = new MessageObject(currentAccount, message, null, null, true, true, eventId); messageObject.currentEvent = event; if (messageObject.contentType >= 0) { @@ -3016,6 +3017,9 @@ public class MessageObject { messageObject.generateLinkDescription(); } } + if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) { + return; + } if (contentType >= 0) { createDateArray(currentAccount, event, messageObjects, messagesByDays, addToEnd); if (addToEnd) { @@ -5330,13 +5334,13 @@ public class MessageObject { } } } - } else if (sponsoredWebPage != null && sponsoredWebPage.photo != null) { + } else if (sponsoredPhoto != null) { if (!update || photoThumbs == null) { - photoThumbs = new ArrayList<>(sponsoredWebPage.photo.sizes); + photoThumbs = new ArrayList<>(sponsoredPhoto.sizes); } else if (!photoThumbs.isEmpty()) { - updatePhotoSizeLocations(photoThumbs, sponsoredWebPage.photo.sizes); + updatePhotoSizeLocations(photoThumbs, sponsoredPhoto.sizes); } - photoThumbsObject = sponsoredWebPage.photo; + photoThumbsObject = sponsoredPhoto; if (strippedThumb == null) { createStrippedThumb(); } @@ -5587,7 +5591,7 @@ public class MessageObject { if (!TextUtils.isEmpty(linkDescription)) { if (containsUrls(linkDescription)) { try { - AndroidUtilities.addLinks((Spannable) linkDescription, Linkify.WEB_URLS); + AndroidUtilities.addLinksSafe((Spannable) linkDescription, Linkify.WEB_URLS, false, true); } catch (Exception e) { FileLog.e(e); } @@ -5708,7 +5712,7 @@ public class MessageObject { if (useManualParse) { if (containsUrls(caption)) { try { - AndroidUtilities.addLinks((Spannable) caption, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS); + AndroidUtilities.addLinksSafe((Spannable) caption, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, false, true); } catch (Exception e) { FileLog.e(e); } @@ -5920,13 +5924,13 @@ public class MessageObject { if (messageText instanceof Spannable && containsUrls(messageText)) { if (messageText.length() < 1000) { try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, internalOnly); + AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, internalOnly, false); } catch (Exception e) { FileLog.e(e); } } else { try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS, internalOnly); + AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS, internalOnly, false); } catch (Exception e) { FileLog.e(e); } @@ -8291,6 +8295,39 @@ public class MessageObject { return fallback; } + + public static ArrayList findStickerEmoticons(TLRPC.Document document, Integer currentAccountForFull) { + if (document == null) { + return null; + } + ArrayList emojis = new ArrayList<>(); + for (int a = 0, N = document.attributes.size(); a < N; a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeCustomEmoji || + attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (currentAccountForFull != null) { + TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccountForFull).getStickerSet(attribute.stickerset, true); + if (set != null && set.packs != null) { + for (int p = 0; p < set.packs.size(); ++p) { + TLRPC.TL_stickerPack pack = set.packs.get(p); + if (pack.documents.contains(document.id) && Emoji.getEmojiDrawable(pack.emoticon) != null) { + emojis.add(pack.emoticon); + } + } + } + if (!emojis.isEmpty()) { + return emojis; + } + } + if (!TextUtils.isEmpty(attribute.alt) && Emoji.getEmojiDrawable(attribute.alt) != null) { + emojis.add(attribute.alt); + return emojis; + } + } + } + return null; + } + public static boolean isAnimatedEmoji(TLRPC.Document document) { if (document == null) { return false; @@ -9650,7 +9687,12 @@ public class MessageObject { } } } + if (newReaction == null) { + int maxChatReactions = MessagesController.getInstance(currentAccount).getChatMaxUniqReactions(getDialogId()); + if (messageOwner.reactions.results.size() + 1 > maxChatReactions) { + return false; + } newReaction = new TLRPC.TL_reactionCount(); newReaction.reaction = visibleReaction.toTLReaction(); messageOwner.reactions.results.add(newReaction); @@ -9811,7 +9853,7 @@ public class MessageObject { public static CharSequence peerNameWithIcon(int currentAccount, TLRPC.Peer peer) { return peerNameWithIcon(currentAccount, peer, !(peer instanceof TLRPC.TL_peerUser)); } - + public static CharSequence peerNameWithIcon(int currentAccount, TLRPC.Peer peer, boolean anotherChat) { if (peer instanceof TLRPC.TL_peerUser) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(peer.user_id); @@ -9932,7 +9974,7 @@ public class MessageObject { return hasLinkPreview && !isGiveawayOrGiveawayResults() && webpage != null && (webpage.photo != null || isVideoDocument(webpage.document)) && !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && - !(isSponsored() && sponsoredWebPage == null && sponsoredChannelPost == 0) && // drawInstantViewType = 1 + !isSponsored() && // drawInstantViewType = 1 !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java index b500c29ec..14695dd10 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java @@ -348,7 +348,7 @@ public class MessagePreviewParams { try { Spannable spanned = SpannableString.valueOf(text); try { - AndroidUtilities.addLinks(spanned, Linkify.WEB_URLS); + AndroidUtilities.addLinksSafe(spanned, Linkify.WEB_URLS, false, true); } catch (Exception e2) { FileLog.e(e2); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index f3cc6fb46..58041d37b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -10,6 +10,7 @@ package org.telegram.messenger; import static org.telegram.messenger.NotificationsController.TYPE_CHANNEL; import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_MESSAGES; import android.Manifest; import android.app.Activity; @@ -61,6 +62,7 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Business.QuickRepliesController; +import org.telegram.ui.ChannelMonetizationLayout; import org.telegram.ui.ChatActivity; import org.telegram.ui.ChatReactionsEditActivity; import org.telegram.ui.ChatRightsEditActivity; @@ -70,13 +72,17 @@ import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.JoinCallAlert; import org.telegram.ui.Components.MotionBackgroundDrawable; +import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftToUsersBottomSheet; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.SwipeGestureSettingsView; import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.DialogsActivity; import org.telegram.ui.EditWidgetActivity; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.NotificationsSettingsActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; import org.telegram.ui.SecretMediaViewer; @@ -507,6 +513,7 @@ public class MessagesController extends BaseController implements NotificationCe public boolean saveGifsWithStickers; private String installReferer; public Set pendingSuggestions; + public Set dismissedSuggestions; public Set exportUri; public Set exportGroupUri; public Set exportPrivateUri; @@ -599,6 +606,11 @@ public class MessagesController extends BaseController implements NotificationCe public int businessChatLinksLimit; public boolean channelRevenueWithdrawalEnabled; public boolean newNoncontactPeersRequirePremiumWithoutOwnpremium; + public int reactionsUniqMax; + public String premiumManageSubscriptionUrl; + public boolean androidDisableRoundCamera2; + public int storiesPinnedToTopCountMax; + public boolean showAnnualPerMonth = false; public int savedDialogsPinnedLimitDefault; public int savedDialogsPinnedLimitPremium; @@ -762,6 +774,14 @@ public class MessagesController extends BaseController implements NotificationCe return getUserConfig().isPremium() ? reactionsInChatMax : 1; } + public int getChatMaxUniqReactions(long dialogId) { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId); + if (chatFull != null && (chatFull instanceof TLRPC.TL_chatFull ? (chatFull.flags & 1048576) != 0 : (chatFull.flags2 & 8192) != 0)) { + return chatFull.reactions_limit; + } + return reactionsUniqMax; + } + public boolean isPremiumUser(TLRPC.User currentUser) { return !premiumFeaturesBlocked() && currentUser.premium; } @@ -1409,6 +1429,7 @@ public class MessagesController extends BaseController implements NotificationCe roundVideoBitrate = mainPreferences.getInt("roundVideoBitrate", 1000); roundAudioBitrate = mainPreferences.getInt("roundAudioBitrate", 64); pendingSuggestions = mainPreferences.getStringSet("pendingSuggestions", null); + dismissedSuggestions = mainPreferences.getStringSet("dismissedSuggestions", null); channelsLimitDefault = mainPreferences.getInt("channelsLimitDefault", 500); channelsLimitPremium = mainPreferences.getInt("channelsLimitPremium", 2 * channelsLimitDefault); savedGifsLimitDefault = mainPreferences.getInt("savedGifsLimitDefault", 200); @@ -1518,6 +1539,11 @@ public class MessagesController extends BaseController implements NotificationCe businessChatLinksLimit = mainPreferences.getInt("businessChatLinksLimit", 100); channelRevenueWithdrawalEnabled = mainPreferences.getBoolean("channelRevenueWithdrawalEnabled", false); newNoncontactPeersRequirePremiumWithoutOwnpremium = mainPreferences.getBoolean("newNoncontactPeersRequirePremiumWithoutOwnpremium", false); + reactionsUniqMax = mainPreferences.getInt("reactionsUniqMax", 11); + premiumManageSubscriptionUrl = mainPreferences.getString("premiumManageSubscriptionUrl", ApplicationLoader.isStandaloneBuild() ? "https://t.me/premiumbot?start=status" : "https://play.google.com/store/account/subscriptions?sku=telegram_premium&package=org.telegram.messenger"); + androidDisableRoundCamera2 = mainPreferences.getBoolean("androidDisableRoundCamera2", false); + storiesPinnedToTopCountMax = mainPreferences.getInt("storiesPinnedToTopCountMax", 3); + showAnnualPerMonth = mainPreferences.getBoolean("showAnnualPerMonth", false); scheduleTranscriptionUpdate(); BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID); if (mainPreferences.contains("dcDomainName2")) { @@ -1544,6 +1570,11 @@ public class MessagesController extends BaseController implements NotificationCe } else { pendingSuggestions = new HashSet<>(); } + if (dismissedSuggestions != null) { + dismissedSuggestions = new HashSet<>(dismissedSuggestions); + } else { + dismissedSuggestions = new HashSet<>(); + } exportUri = mainPreferences.getStringSet("exportUri2", null); if (exportUri != null) { @@ -2284,11 +2315,14 @@ public class MessagesController extends BaseController implements NotificationCe getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated); } + private Runnable loadAppConfigRunnable = this::loadAppConfig; + public void loadAppConfig() { loadAppConfig(false); } public void loadAppConfig(boolean force) { + AndroidUtilities.cancelRunOnUIThread(loadAppConfigRunnable); if (force) { appConfigFetcher.forceRequest(currentAccount, 0); } @@ -2296,6 +2330,8 @@ public class MessagesController extends BaseController implements NotificationCe if (config != null && config.config instanceof TLRPC.TL_jsonObject) { applyAppConfig((TLRPC.TL_jsonObject) config.config); } + AndroidUtilities.cancelRunOnUIThread(loadAppConfigRunnable); + AndroidUtilities.runOnUIThread(loadAppConfigRunnable, 4 * 60 * 1000 + 10); })); } @@ -2982,6 +3018,26 @@ public class MessagesController extends BaseController implements NotificationCe } break; } + case "dismissed_suggestions": { + HashSet newSuggestions = new HashSet<>(); + if (value.value instanceof TLRPC.TL_jsonArray) { + TLRPC.TL_jsonArray array = (TLRPC.TL_jsonArray) value.value; + for (int b = 0, N2 = array.value.size(); b < N2; b++) { + TLRPC.JSONValue val = array.value.get(b); + if (val instanceof TLRPC.TL_jsonString) { + TLRPC.TL_jsonString string = (TLRPC.TL_jsonString) val; + newSuggestions.add(string.value); + } + } + } + if (!dismissedSuggestions.equals(newSuggestions)) { + dismissedSuggestions = newSuggestions; + editor.putStringSet("dismissedSuggestions", dismissedSuggestions); + getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable); + changed = true; + } + break; + } case "emojies_sounds": { try { HashMap newEmojies = new HashMap<>(); @@ -3974,6 +4030,61 @@ public class MessagesController extends BaseController implements NotificationCe } break; } + case "reactions_uniq_max": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (num.value != reactionsUniqMax) { + reactionsUniqMax = (int) num.value; + editor.putInt("reactionsUniqMax", reactionsUniqMax); + changed = true; + } + } + break; + } + case "premium_manage_subscription_url": { + if (value.value instanceof TLRPC.TL_jsonString) { + TLRPC.TL_jsonString str = (TLRPC.TL_jsonString) value.value; + if (!TextUtils.equals(str.value, premiumManageSubscriptionUrl)) { + premiumManageSubscriptionUrl = str.value; + editor.putString("premiumManageSubscriptionUrl", premiumManageSubscriptionUrl); + changed = true; + } + } + break; + } + case "android_disable_round_camera2": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != androidDisableRoundCamera2) { + androidDisableRoundCamera2 = bool.value; + editor.putBoolean("androidDisableRoundCamera2", androidDisableRoundCamera2); + changed = true; + } + } + break; + } + case "stories_pinned_to_top_count_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (num.value != storiesPinnedToTopCountMax) { + storiesPinnedToTopCountMax = (int) num.value; + editor.putInt("storiesPinnedToTopCountMax", storiesPinnedToTopCountMax); + changed = true; + } + } + break; + } + case "show_annual_per_month": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != showAnnualPerMonth) { + showAnnualPerMonth = bool.value; + editor.putBoolean("showAnnualPerMonth", showAnnualPerMonth); + changed = true; + } + } + break; + } } } @@ -4505,7 +4616,8 @@ public class MessagesController extends BaseController implements NotificationCe channelRevenueWithdrawalEnabled = false; collectDeviceStats = false; smsjobsStickyNotificationEnabled = false; - mainPreferences.edit().remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").apply(); + showAnnualPerMonth = false; + mainPreferences.edit().remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").remove("showAnnualPerMonth").apply(); } private boolean savePremiumFeaturesPreviewOrder(String key, SparseIntArray array, SharedPreferences.Editor editor, ArrayList value) { @@ -4556,9 +4668,11 @@ public class MessagesController extends BaseController implements NotificationCe return; } if (did == 0) { - if (pendingSuggestions.remove(suggestion)) { + if (pendingSuggestions.remove(suggestion) || !dismissedSuggestions.contains(suggestion)) { + dismissedSuggestions.add(suggestion); SharedPreferences.Editor editor = mainPreferences.edit(); editor.putStringSet("pendingSuggestions", pendingSuggestions); + editor.putStringSet("dismissedSuggestions", dismissedSuggestions); editor.commit(); getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable); } else { @@ -4823,7 +4937,9 @@ public class MessagesController extends BaseController implements NotificationCe public TLRPC.InputPeer getInputPeer(long id) { TLRPC.InputPeer inputPeer; - if (id < 0) { + if (id == getUserConfig().getClientUserId()) { + inputPeer = new TLRPC.TL_inputPeerSelf(); + } else if (id < 0) { TLRPC.Chat chat = getChat(-id); if (ChatObject.isChannel(chat)) { inputPeer = new TLRPC.TL_inputPeerChannel(); @@ -4864,6 +4980,16 @@ public class MessagesController extends BaseController implements NotificationCe return inputPeer; } + public static TLRPC.InputPeer getInputPeer(TLObject userOrChat) { + if (userOrChat instanceof TLRPC.User) { + return getInputPeer((TLRPC.User) userOrChat); + } else if (userOrChat instanceof TLRPC.Chat) { + return getInputPeer((TLRPC.Chat) userOrChat); + } else { + return null; + } + } + public TLRPC.Peer getPeer(long id) { TLRPC.Peer inputPeer; if (id < 0) { @@ -7294,6 +7420,10 @@ public class MessagesController extends BaseController implements NotificationCe } public void setParticipantBannedRole(long chatId, TLRPC.User user, TLRPC.Chat chat, TLRPC.TL_chatBannedRights rights, boolean isChannel, BaseFragment parentFragment) { + setParticipantBannedRole(chatId, user, chat, rights, isChannel, parentFragment, null); + } + + public void setParticipantBannedRole(long chatId, TLRPC.User user, TLRPC.Chat chat, TLRPC.TL_chatBannedRights rights, boolean isChannel, BaseFragment parentFragment, Runnable whenDone) { if (user == null && chat == null || rights == null) { return; } @@ -7309,6 +7439,9 @@ public class MessagesController extends BaseController implements NotificationCe if (error == null) { processUpdates((TLRPC.Updates) response, false); AndroidUtilities.runOnUIThread(() -> loadFullChat(chatId, 0, true), 1000); + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } } else { AndroidUtilities.runOnUIThread(() -> AlertsCreator.processError(currentAccount, error, parentFragment, req, isChannel)); } @@ -10694,7 +10827,7 @@ public class MessagesController extends BaseController implements NotificationCe editor1.commit(); } - loadingNotificationSettings = 3; + loadingNotificationSettings = 4; for (int a = 0; a < 3; a++) { TLRPC.TL_account_getNotifySettings req = new TLRPC.TL_account_getNotifySettings(); if (a == 0) { @@ -10763,7 +10896,7 @@ public class MessagesController extends BaseController implements NotificationCe } } getNotificationsController().getNotificationsSettingsFacade().applySoundSettings(notify_settings.android_sound, editor, 0, 0, type, false); - editor.commit(); + editor.apply(); if (loadingNotificationSettings == 0) { getUserConfig().notificationsSettingsLoaded = true; getUserConfig().saveConfig(false); @@ -10771,12 +10904,57 @@ public class MessagesController extends BaseController implements NotificationCe } })); } + + getConnectionsManager().sendRequest(new TLRPC.TL_account_getReactionsNotifySettings(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { + loadingNotificationSettings--; + if (res instanceof TLRPC.TL_reactionsNotifySettings) { + TLRPC.TL_reactionsNotifySettings notify_settings = (TLRPC.TL_reactionsNotifySettings) res; + SharedPreferences.Editor editor = notificationsPreferences.edit(); + editor.putBoolean("EnableReactionsMessages", notify_settings.messages_notify_from != null); + if (notify_settings.messages_notify_from != null) { + editor.putBoolean("EnableReactionsMessagesContacts", notify_settings.messages_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsStories", notify_settings.stories_notify_from != null); + if (notify_settings.stories_notify_from != null) { + editor.putBoolean("EnableReactionsStoriesContacts", notify_settings.stories_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsPreview", notify_settings.show_previews); + getNotificationsController().getNotificationsSettingsFacade().applySoundSettings(notify_settings.sound, editor, 0, 0, TYPE_REACTIONS_MESSAGES, false); + editor.apply(); + } + if (loadingNotificationSettings == 0) { + getUserConfig().notificationsSettingsLoaded = true; + getUserConfig().saveConfig(false); + } + })); } if (!getUserConfig().notificationsSignUpSettingsLoaded) { loadSignUpNotificationsSettings(); } } + public void reloadReactionsNotifySettings() { + getConnectionsManager().sendRequest(new TLRPC.TL_account_getReactionsNotifySettings(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TLRPC.TL_reactionsNotifySettings) { + TLRPC.TL_reactionsNotifySettings notify_settings = (TLRPC.TL_reactionsNotifySettings) res; + SharedPreferences.Editor editor = notificationsPreferences.edit(); + editor.putBoolean("EnableReactionsMessages", notify_settings.messages_notify_from != null); + if (notify_settings.messages_notify_from != null) { + editor.putBoolean("EnableReactionsMessagesContacts", notify_settings.messages_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsStories", notify_settings.stories_notify_from != null); + if (notify_settings.stories_notify_from != null) { + editor.putBoolean("EnableReactionsStoriesContacts", notify_settings.stories_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsPreview", notify_settings.show_previews); + getNotificationsController().getNotificationsSettingsFacade().applySoundSettings(notify_settings.sound, editor, 0, 0, TYPE_REACTIONS_MESSAGES, false); + editor.apply(); + + getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated); + } + })); + } + public void loadSignUpNotificationsSettings() { if (!loadingNotificationSignUpSettings) { loadingNotificationSignUpSettings = true; @@ -13581,6 +13759,10 @@ public class MessagesController extends BaseController implements NotificationCe } public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer, boolean forceDelete, boolean revoke) { + deleteParticipantFromChat(chatId, peer, forceDelete, revoke, null); + } + + public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer, boolean forceDelete, boolean revoke, Runnable whenDone) { if (peer == null) { return; } @@ -13623,7 +13805,6 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.TL_messages_deleteChat req = new TLRPC.TL_messages_deleteChat(); req.chat_id = chatId; getConnectionsManager().sendRequest(req, (response, error) -> { - }); return; } @@ -13645,6 +13826,9 @@ public class MessagesController extends BaseController implements NotificationCe if (isChannel && !self) { AndroidUtilities.runOnUIThread(() -> loadFullChat(chatId, 0, true), 1000); } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } }, ConnectionsManager.RequestFlagInvokeAfter); } @@ -14431,6 +14615,7 @@ public class MessagesController extends BaseController implements NotificationCe long[] ids = corrected.valueAt(a); getSendMessagesHelper().processSentMessage((int) ids[1]); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, (int) ids[1], newId, null, ids[0], 0L, -1, false); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, (int) ids[1], newId, null, ids[0], 0L, -1, false); } }); } @@ -14687,6 +14872,7 @@ public class MessagesController extends BaseController implements NotificationCe long[] ids = corrected.valueAt(a); getSendMessagesHelper().processSentMessage((int) ids[1]); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, (int) ids[1], newId, null, ids[0], 0L, -1, false); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, (int) ids[1], newId, null, ids[0], 0L, -1, false); } }); } @@ -17486,6 +17672,41 @@ public class MessagesController extends BaseController implements NotificationCe if (UserObject.isUserSelf(currentUser)) { getNotificationCenter().postNotificationName(NotificationCenter.mainUserInfoChanged); } + } else if (baseUpdate instanceof TLRPC.TL_updateNewStoryReaction) { + TLRPC.TL_updateNewStoryReaction update = (TLRPC.TL_updateNewStoryReaction) baseUpdate; + long dialogId = DialogObject.getPeerDialogId(update.peer); + int story_id = update.story_id; + TLRPC.Message msg = new TLRPC.Message(); + msg.id = -story_id; + msg.dialog_id = dialogId; + msg.peer_id = getPeer(dialogId); + msg.date = getConnectionsManager().getCurrentTime(); + TLRPC.User user = getMessagesController().getUser(msg.dialog_id); + if (user != null && getNotificationsSettings(currentAccount).getBoolean("EnableReactionsPreview", true)) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(update.reaction).flatten(); + if (reaction.emojicon != null) { + msg.message = LocaleController.formatString(R.string.PushReactStory, UserObject.getFirstName(user), reaction.emojicon); + } else { + msg.message = LocaleController.formatString(R.string.PushReactStoryHidden); + } + } else { + msg.message = LocaleController.formatString(R.string.PushReactStoryHidden); + } + ArrayList messageObjects = new ArrayList(); + MessageObject message = new MessageObject(currentAccount, msg, false, false); + message.isStoryReactionPush = true; + message.localType = 1; + if (user != null) { + message.localUserName = UserObject.getFirstName(user); + } + messageObjects.add(message); + getNotificationsController().processNewMessages(messageObjects, true, false, null); + } else if (baseUpdate instanceof TLRPC.TL_updateBroadcastRevenueTransactions) { + TLRPC.TL_updateBroadcastRevenueTransactions update = (TLRPC.TL_updateBroadcastRevenueTransactions) baseUpdate; + if (ChannelMonetizationLayout.instance != null) { + ChannelMonetizationLayout.instance.setupBalances(update.balances); + ChannelMonetizationLayout.instance.reloadTransactions(); + } } else if (baseUpdate instanceof TLRPC.TL_updateUser) { TLRPC.TL_updateUser update = (TLRPC.TL_updateUser) baseUpdate; TLRPC.User currentUser = getUser(update.user_id); @@ -17525,7 +17746,7 @@ public class MessagesController extends BaseController implements NotificationCe toDbUser.id = update.user_id; toDbUser.phone = update.phone; dbUsers.add(toDbUser); - } else if (baseUpdate instanceof TLRPC.TL_updateNotifySettings) { + } else if (baseUpdate instanceof TLRPC.TL_updateNotifySettings) { TLRPC.TL_updateNotifySettings update = (TLRPC.TL_updateNotifySettings) baseUpdate; if (update.notify_settings instanceof TLRPC.TL_peerNotifySettings) { updateDialogFiltersFlags |= DIALOG_FILTER_FLAG_EXCLUDE_MUTED; @@ -18673,7 +18894,7 @@ public class MessagesController extends BaseController implements NotificationCe if (topicId != 0) { return isDialogMuted(dialogId, 0, chat); } else { - return !getNotificationsController().isGlobalNotificationsEnabled(dialogId, forceChannel); + return !getNotificationsController().isGlobalNotificationsEnabled(dialogId, forceChannel, false, false); } } if (mute_type == 2) { @@ -18764,24 +18985,20 @@ public class MessagesController extends BaseController implements NotificationCe message.flags |= 128; } message.peer_id = getPeer(dialogId); - message.from_id = sponsoredMessage.from_id; message.flags |= 256; message.date = getConnectionsManager().getCurrentTime(); message.id = messageId--; MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true, true); messageObject.sponsoredId = sponsoredMessage.random_id; - messageObject.botStartParam = sponsoredMessage.start_param; - messageObject.sponsoredChannelPost = sponsoredMessage.channel_post; - messageObject.sponsoredChatInvite = sponsoredMessage.chat_invite; - messageObject.sponsoredChatInviteHash = sponsoredMessage.chat_invite_hash; + messageObject.sponsoredTitle = sponsoredMessage.title; + messageObject.sponsoredUrl = sponsoredMessage.url; messageObject.sponsoredRecommended = sponsoredMessage.recommended; - messageObject.sponsoredShowPeerPhoto = sponsoredMessage.show_peer_photo; + messageObject.sponsoredPhoto = sponsoredMessage.photo; messageObject.sponsoredInfo = sponsoredMessage.sponsor_info; messageObject.sponsoredAdditionalInfo = sponsoredMessage.additional_info; - messageObject.sponsoredWebPage = sponsoredMessage.webpage; - messageObject.sponsoredBotApp = sponsoredMessage.app; messageObject.sponsoredButtonText = sponsoredMessage.button_text; messageObject.sponsoredCanReport = sponsoredMessage.can_report; + messageObject.sponsoredColor = sponsoredMessage.color; result.add(messageObject); } } @@ -19831,7 +20048,7 @@ public class MessagesController extends BaseController implements NotificationCe }); } - public void setCustomChatReactions(long chatId, int type, List reactions, Utilities.Callback onError, Runnable onSuccess) { + public void setCustomChatReactions(long chatId, int type, List reactions, int reactionsCount, Utilities.Callback onError, Runnable onSuccess) { TLRPC.TL_messages_setChatAvailableReactions req = new TLRPC.TL_messages_setChatAvailableReactions(); req.peer = getInputPeer(-chatId); if (type == ChatReactionsEditActivity.SELECT_TYPE_NONE || reactions.isEmpty()) { @@ -19843,6 +20060,8 @@ public class MessagesController extends BaseController implements NotificationCe req.available_reactions = someReactions; someReactions.reactions.addAll(reactions); } + req.flags |= 1; + req.reactions_limit = reactionsCount; getConnectionsManager().sendRequest(req, (response, error) -> { if (response != null) { processUpdates((TLRPC.Updates) response, false); @@ -19871,6 +20090,17 @@ public class MessagesController extends BaseController implements NotificationCe }); } }); + + TLRPC.ChatFull chatFull = getChatFull(chatId); + if (chatFull != null) { + if (chatFull instanceof TLRPC.TL_channelFull) { + chatFull.flags2 |= 8192; + } else { + chatFull.flags |= 1048576; + } + chatFull.reactions_limit = reactionsCount; + getMessagesStorage().updateChatInfo(chatFull, false); + } } public void setChatReactions(long chatId, int type, List reactions) { @@ -19975,6 +20205,24 @@ public class MessagesController extends BaseController implements NotificationCe return false; } + public void getChannelParticipant(TLRPC.Chat chat, TLRPC.User user, Utilities.Callback callback) { + if (chat == null || user == null) { + if (callback != null) { + callback.run(null); + } + return; + } + TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); + req.channel = getInputChannel(chat.id); + req.participant = getInputPeer(user); + getConnectionsManager().sendRequest(req, (res, err) -> { + if (callback != null) { + TLRPC.ChannelParticipant participant = res instanceof TLRPC.TL_channels_channelParticipant ? ((TLRPC.TL_channels_channelParticipant) res).participant : null; + callback.run(participant); + } + }); + } + public void checkIsInChat(boolean tryCacheFirst, TLRPC.Chat chat, TLRPC.User user, IsInChatCheckedCallback callback) { if (chat == null || user == null) { if (callback != null) { @@ -20397,9 +20645,16 @@ public class MessagesController extends BaseController implements NotificationCe } private HashMap cachedChannelRecommendations; + public ChannelRecommendations getCachedChannelRecommendations(long chatId) { + if (cachedChannelRecommendations == null) { + return null; + } + return cachedChannelRecommendations.get(chatId); + } + public ChannelRecommendations getChannelRecommendations(long chatId) { TLRPC.InputChannel inputChannel = getInputChannel(chatId); - if (inputChannel == null) { + if (inputChannel == null && chatId != 0) { return null; } if (cachedChannelRecommendations == null) { @@ -20415,7 +20670,10 @@ public class MessagesController extends BaseController implements NotificationCe } cachedChannelRecommendations.put(chatId, null); TLRPC.TL_channels_getChannelRecommendations req = new TLRPC.TL_channels_getChannelRecommendations(); - req.channel = inputChannel; + if (chatId != 0) { + req.flags |= 1; + req.channel = inputChannel; + } getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.messages_Chats) { ArrayList chats = ((TLRPC.messages_Chats) res).chats; @@ -20907,4 +21165,22 @@ public class MessagesController extends BaseController implements NotificationCe } })); } + + public void disableAds(boolean send) { + TLRPC.UserFull userFull = getUserFull(getUserConfig().getClientUserId()); + if (userFull == null) return; + userFull.sponsored_enabled = false; + getMessagesStorage().updateUserInfo(userFull, false); + if (send) { + TLRPC.TL_account_toggleSponsoredMessages req = new TLRPC.TL_account_toggleSponsoredMessages(); + req.enabled = false; + getConnectionsManager().sendRequest(req, null); + } + } + + public boolean isSponsoredDisabled() { + TLRPC.UserFull userFull = getUserFull(getUserConfig().getClientUserId()); + if (userFull == null) return false; + return !userFull.sponsored_enabled; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 39bd7203b..1a5b3d505 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -104,7 +104,7 @@ public class MessagesStorage extends BaseController { } } - public final static int LAST_DB_VERSION = 152; + public final static int LAST_DB_VERSION = 153; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -698,7 +698,7 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE stories (dialog_id INTEGER, story_id INTEGER, data BLOB, custom_params BLOB, PRIMARY KEY (dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE stories_counter (dialog_id INTEGER PRIMARY KEY, count INTEGER, max_read INTEGER);").stepThis().dispose(); - database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, type INTEGER, seen INTEGER, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose(); + database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, type INTEGER, seen INTEGER, pin INTEGER, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE story_drafts (id INTEGER PRIMARY KEY, date INTEGER, data BLOB, type INTEGER);").stepThis().dispose(); @@ -1312,6 +1312,16 @@ public class MessagesStorage extends BaseController { }); } + public void deleteAllStoryReactionPushMessages() { + storageQueue.postRunnable(() -> { + try { + database.executeFast("DELETE FROM unread_push_messages WHERE is_reaction = 2").stepThis().dispose(); + } catch (Exception e) { + checkSQLException(e); + } + }); + } + public void putPushMessage(MessageObject message) { storageQueue.postRunnable(() -> { try { @@ -1350,7 +1360,7 @@ public class MessagesStorage extends BaseController { } state.bindInteger(9, flags); state.bindLong(10, MessageObject.getTopicId(currentAccount, message.messageOwner, false)); - state.bindInteger(11, message.isReactionPush ? 1 : 0); + state.bindInteger(11, (message.isReactionPush ? 1 : 0) + (message.isStoryReactionPush ? 1 : 0)); state.step(); data.reuse(); @@ -3717,7 +3727,9 @@ public class MessagesStorage extends BaseController { } MessageObject messageObject = new MessageObject(currentAccount, message, messageText, name, userName, (flags & 1) != 0, (flags & 2) != 0, (message.flags & 0x80000000) != 0, false); - messageObject.isReactionPush = cursor.intValue(10) != 0; + final int is_reaction = cursor.intValue(10); + messageObject.isReactionPush = is_reaction == 1; + messageObject.isStoryReactionPush = is_reaction == 2; pushMessages.add(messageObject); addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, null); } @@ -5175,7 +5187,7 @@ public class MessagesStorage extends BaseController { TLRPC.Message message = new TLRPC.TL_message(); SQLiteCursor cursor = null; try { - cursor = database.queryFinalized("SELECT custom_params FROM messages_v2 WHERE mid = " + messageId + " AND uid = " + dialogId); + cursor = database.queryFinalized("SELECT custom_params FROM messages_v2 WHERE mid = ? AND uid = ?", messageId, dialogId); boolean read = false; if (cursor.next()) { MessageCustomParamsHelper.readLocalParams(message, cursor.byteBufferValue(0)); @@ -5184,7 +5196,7 @@ public class MessagesStorage extends BaseController { cursor.dispose(); cursor = null; if (!read) { - cursor = database.queryFinalized("SELECT custom_params FROM messages_topics WHERE mid = " + messageId + " AND uid = " + dialogId); + cursor = database.queryFinalized("SELECT custom_params FROM messages_topics WHERE mid = ? AND uid = ?", messageId, dialogId); if (cursor.next()) { MessageCustomParamsHelper.readLocalParams(message, cursor.byteBufferValue(0)); read = true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java index 146034f27..1bde9e6e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java @@ -706,6 +706,9 @@ public class MusicPlayerService extends Service implements NotificationCenter.No } } else if (id == NotificationCenter.messagePlayingDidSeek) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject == null) { + return; + } long progress = Math.round(messageObject.audioPlayerDuration * (float) args[1]) * 1000L; updatePlaybackState(progress); if (remoteControlClient != null && Build.VERSION.SDK_INT >= 18) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 51097f7ad..113136d09 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -44,6 +44,7 @@ public class NotificationCenter { public static final int loadingMessagesFailed = totalEvents++; public static final int messageReceivedByAck = totalEvents++; public static final int messageReceivedByServer = totalEvents++; + public static final int messageReceivedByServer2 = totalEvents++; public static final int messageSendError = totalEvents++; public static final int forceImportContactsStart = totalEvents++; public static final int contactsDidLoad = totalEvents++; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java index c5d763be4..d3016505f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java @@ -27,6 +27,8 @@ public class NotificationDismissReceiver extends BroadcastReceiver { int date = intent.getIntExtra("messageDate", 0); if (intent.hasExtra("story") && intent.getBooleanExtra("story", false)) { NotificationsController.getInstance(currentAccount).processIgnoreStories(); + } else if (intent.hasExtra("storyReaction") && intent.getBooleanExtra("storyReaction", false)) { + NotificationsController.getInstance(currentAccount).processIgnoreStoryReactions(); } else if (dialogId == 0) { MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dismissDate", date).commit(); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 3e806e8ab..ef0054d76 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -253,7 +253,11 @@ public class NotificationsController extends BaseController { } NotificationChannel notificationChannel = systemNotificationManager.getNotificationChannel(OTHER_NOTIFICATIONS_CHANNEL); if (notificationChannel != null && notificationChannel.getImportance() == NotificationManager.IMPORTANCE_NONE) { - systemNotificationManager.deleteNotificationChannel(OTHER_NOTIFICATIONS_CHANNEL); + try { + systemNotificationManager.deleteNotificationChannel(OTHER_NOTIFICATIONS_CHANNEL); + } catch (Exception e) { + FileLog.e(e); + } OTHER_NOTIFICATIONS_CHANNEL = null; notificationChannel = null; } @@ -319,7 +323,7 @@ public class NotificationsController extends BaseController { SharedPreferences.Editor editor = preferences.edit(); long flags; boolean override = topicId != 0; - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did, false, false); String sharedPrefKey = NotificationsController.getSharedPrefKey(did, topicId); if (selectedTimeInSeconds == Integer.MAX_VALUE) { @@ -511,6 +515,8 @@ public class NotificationsController extends BaseController { int mid = mids.get(b); MessageObject messageObject = sparseArray.get(mid); if (messageObject != null) { + if (messageObject.isStoryReactionPush) + continue; if (isReactions && !messageObject.isReactionPush) { continue; } @@ -664,6 +670,31 @@ public class NotificationsController extends BaseController { }); } + public void processSeenStoryReactions(long dialogId, int storyId) { + if (dialogId != getUserConfig().getClientUserId()) + return; + notificationsQueue.postRunnable(() -> { + boolean changed = false; + for (int i = 0; i < pushMessages.size(); ++i) { + MessageObject msgObject = pushMessages.get(i); + if (msgObject.isStoryReactionPush && Math.abs(msgObject.getId()) == storyId) { + pushMessages.remove(i); + SparseArray msgs = pushMessagesDict.get(msgObject.getDialogId()); + if (msgs != null) msgs.remove(msgObject.getId()); + if (msgs != null && msgs.size() <= 0) pushMessagesDict.remove(msgObject.getDialogId()); + ArrayList ids = new ArrayList<>(); + ids.add(msgObject.getId()); + getMessagesStorage().deletePushMessages(msgObject.getDialogId(), ids); + i--; + changed = true; + } + } + if (changed) { + showOrUpdateNotification(false); + } + }); + } + public void processDeleteStory(long dialogId, int storyId) { notificationsQueue.postRunnable(() -> { boolean changed = false; @@ -723,6 +754,27 @@ public class NotificationsController extends BaseController { }); } + public void processIgnoreStoryReactions() { + notificationsQueue.postRunnable(() -> { + boolean changed = false; + for (int i = 0; i < pushMessages.size(); ++i) { + MessageObject msg = pushMessages.get(i); + if (msg != null && msg.isStoryReactionPush) { + pushMessages.remove(i); + i--; + SparseArray arr = pushMessagesDict.get(msg.getDialogId()); + if (arr != null) arr.remove(msg.getId()); + if (arr != null && arr.size() <= 0) pushMessagesDict.remove(msg.getDialogId()); + changed = true; + } + } + getMessagesStorage().deleteAllStoryReactionPushMessages(); + if (changed) { + showOrUpdateNotification(false); + } + }); + } + public void processIgnoreStories(long dialogId) { notificationsQueue.postRunnable(() -> { boolean changed = !storyPushMessages.isEmpty(); @@ -735,6 +787,10 @@ public class NotificationsController extends BaseController { }); } + public void processReadStories() { + + } + public void processReadMessages(LongSparseIntArray inbox, long dialogId, int maxDate, int maxId, boolean isPopup) { ArrayList popupArrayRemove = new ArrayList<>(0); notificationsQueue.postRunnable(() -> { @@ -744,13 +800,15 @@ public class NotificationsController extends BaseController { int messageId = inbox.get(key); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == key && messageObject.getId() <= messageId) { + if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == key && messageObject.getId() <= messageId && !messageObject.isStoryReactionPush) { if (isPersonalMessage(messageObject)) { personalCount--; } popupArrayRemove.add(messageObject); long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -772,7 +830,7 @@ public class NotificationsController extends BaseController { if (dialogId != 0 && (maxId != 0 || maxDate != 0)) { for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == dialogId) { + if (messageObject.getDialogId() == dialogId && !messageObject.isStoryReactionPush) { boolean remove = false; if (maxDate != 0) { if (messageObject.messageOwner.date <= maxDate) { @@ -794,7 +852,9 @@ public class NotificationsController extends BaseController { personalCount--; } long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -826,6 +886,7 @@ public class NotificationsController extends BaseController { } private int addToPopupMessages(ArrayList popupArrayAdd, MessageObject messageObject, long dialogId, boolean isChannel, SharedPreferences preferences) { + if (messageObject.isStoryReactionPush) return 0; int popup = 0; if (!DialogObject.isEncryptedDialog(dialogId)) { if (preferences.getBoolean("custom_" + dialogId, false)) { @@ -865,7 +926,9 @@ public class NotificationsController extends BaseController { for (int b = 0, N2 = messages.size(); b < N2; b++) { MessageObject messageObject = messages.get(b); long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -875,7 +938,7 @@ public class NotificationsController extends BaseController { break; } MessageObject oldMessage = sparseArray.get(messageObject.getId()); - if (oldMessage != null && oldMessage.isReactionPush) { + if (oldMessage != null && (oldMessage.isReactionPush || oldMessage.isStoryReactionPush)) { oldMessage = null; } if (oldMessage != null) { @@ -967,7 +1030,9 @@ public class NotificationsController extends BaseController { isChannel = false; } long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -1007,7 +1072,7 @@ public class NotificationsController extends BaseController { long originalDialogId = dialogId; long topicId = MessageObject.getTopicId(currentAccount, messageObject.messageOwner, getMessagesController().isForum(messageObject)); - if (dialogId == openedDialogId && ApplicationLoader.isScreenOn) { + if (dialogId == openedDialogId && ApplicationLoader.isScreenOn && !messageObject.isStoryReactionPush) { if (!isFcm) { playInChatSound(); } @@ -1032,7 +1097,7 @@ public class NotificationsController extends BaseController { } else { int notifyOverride = getNotifyOverride(preferences, dialogId, topicId); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialogId, isChannel); + value = isGlobalNotificationsEnabled(dialogId, isChannel, messageObject.isReactionPush, messageObject.isStoryReactionPush); /*if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { FileLog.d("global notify settings for " + dialog_id + " = " + value); }*/ @@ -1113,7 +1178,7 @@ public class NotificationsController extends BaseController { int notifyOverride = getNotifyOverride(preferences, dialog_id, topicId); boolean canAddValue; if (notifyOverride == -1) { - canAddValue = isGlobalNotificationsEnabled(dialog_id, isChannel); + canAddValue = isGlobalNotificationsEnabled(dialog_id, isChannel, messageObject.isReactionPush, messageObject.isStoryReactionPush); } else { canAddValue = notifyOverride != 2; } @@ -1208,7 +1273,7 @@ public class NotificationsController extends BaseController { if (!forum) { int notifyOverride = getNotifyOverride(preferences, dialogId, 0); if (notifyOverride == -1) { - canAddValue = isGlobalNotificationsEnabled(dialogId); + canAddValue = isGlobalNotificationsEnabled(dialogId, false, false); } else { canAddValue = notifyOverride != 2; } @@ -1248,7 +1313,7 @@ public class NotificationsController extends BaseController { pushDialogsOverrideMention.remove(dialogId); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == dialogId) { + if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == dialogId && !messageObject.isStoryReactionPush) { if (isPersonalMessage(messageObject)) { personalCount--; } @@ -1362,7 +1427,7 @@ public class NotificationsController extends BaseController { } else { int notifyOverride = getNotifyOverride(preferences, dialog_id, topicId); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialog_id); + value = isGlobalNotificationsEnabled(dialog_id, messageObject.isReactionPush, messageObject.isStoryReactionPush); } else { value = notifyOverride != 2; } @@ -1392,7 +1457,7 @@ public class NotificationsController extends BaseController { } else { int notifyOverride = getNotifyOverride(preferences, dialog_id, 0); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialog_id); + value = isGlobalNotificationsEnabled(dialog_id, false, false); } else { value = notifyOverride != 2; } @@ -1435,7 +1500,7 @@ public class NotificationsController extends BaseController { } else { int notifyOverride = getNotifyOverride(preferences, dialogId, topicId); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialogId); + value = isGlobalNotificationsEnabled(dialogId, messageObject.isReactionPush, messageObject.isStoryReactionPush); } else { value = notifyOverride != 2; } @@ -1446,7 +1511,9 @@ public class NotificationsController extends BaseController { } if (mid != 0) { long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -1893,9 +1960,9 @@ public class NotificationsController extends BaseController { } 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("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -1965,9 +2032,9 @@ public class NotificationsController extends BaseController { } 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("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2037,9 +2104,9 @@ public class NotificationsController extends BaseController { } 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); + return LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2377,9 +2444,9 @@ public class NotificationsController extends BaseController { } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationMessageQuiz2", R.string.NotificationMessageQuiz2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessageQuiz2", R.string.NotificationMessageQuiz2, name, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, name, mediaPoll.poll.question.text); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { msg = LocaleController.formatString("NotificationMessageMap", R.string.NotificationMessageMap, name); @@ -2600,9 +2667,9 @@ public class NotificationsController extends BaseController { } 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("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2672,9 +2739,9 @@ public class NotificationsController extends BaseController { } 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("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2746,9 +2813,9 @@ public class NotificationsController extends BaseController { } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("ChannelMessageQuiz2", R.string.ChannelMessageQuiz2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("ChannelMessageQuiz2", R.string.ChannelMessageQuiz2, name, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question.text); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; @@ -2819,9 +2886,9 @@ public class NotificationsController extends BaseController { } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationMessageGroupQuiz2", R.string.NotificationMessageGroupQuiz2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessageGroupQuiz2", R.string.NotificationMessageGroupQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, name, chat.title, mediaPoll.poll.question.text); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { msg = LocaleController.formatString("NotificationMessageGroupGame", R.string.NotificationMessageGroupGame, name, chat.title, messageObject.messageOwner.media.game.title); @@ -2897,7 +2964,7 @@ public class NotificationsController extends BaseController { private boolean isPersonalMessage(MessageObject messageObject) { return messageObject.messageOwner.peer_id != null && messageObject.messageOwner.peer_id.chat_id == 0 && messageObject.messageOwner.peer_id.channel_id == 0 - && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty); + && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) || messageObject.isStoryReactionPush; } private int getNotifyOverride(SharedPreferences preferences, long dialog_id, long topicId) { @@ -3118,6 +3185,8 @@ public class NotificationsController extends BaseController { key = "groups"; } else if (type == TYPE_STORIES) { key = "stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + key = "reactions"; } else { key = "private"; } @@ -3143,6 +3212,8 @@ public class NotificationsController extends BaseController { key = "groups_ia"; } else if (type == TYPE_STORIES) { key = "stories_ia"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + key = "reactions_ia"; } else { key = "private_ia"; } @@ -3166,6 +3237,8 @@ public class NotificationsController extends BaseController { overwriteKey = "overwrite_group"; } else if (type == TYPE_STORIES) { overwriteKey = "overwrite_stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + overwriteKey = "overwrite_reactions"; } else { overwriteKey = "overwrite_private"; } @@ -3291,7 +3364,7 @@ public class NotificationsController extends BaseController { protected void ensureGroupsCreated() { SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); if (groupsCreated == null) { - groupsCreated = preferences.getBoolean("groupsCreated4", false); + groupsCreated = preferences.getBoolean("groupsCreated5", false); } if (!groupsCreated) { try { @@ -3312,7 +3385,12 @@ public class NotificationsController extends BaseController { editor = getAccountInstance().getNotificationsSettings().edit(); } editor.remove("priority_channel").remove("vibrate_channel").remove("ChannelSoundPath").remove("ChannelSound"); - } else if (id.contains("_groups_")) { + } else if (id.contains("_reactions_")) { + if (editor == null) { + editor = getAccountInstance().getNotificationsSettings().edit(); + } + editor.remove("priority_react").remove("vibrate_react").remove("ReactionSoundPath").remove("ReactionSound"); + } else if (id.contains("_groups_")) { if (editor == null) { editor = getAccountInstance().getNotificationsSettings().edit(); } @@ -3342,7 +3420,7 @@ public class NotificationsController extends BaseController { } catch (Exception e) { FileLog.e(e); } - preferences.edit().putBoolean("groupsCreated4", true).commit(); + preferences.edit().putBoolean("groupsCreated5", true).commit(); groupsCreated = true; } if (!channelGroupsCreated) { @@ -3351,6 +3429,7 @@ public class NotificationsController extends BaseController { String groupsId = "groups" + currentAccount; String privateId = "private" + currentAccount; String storiesId = "stories" + currentAccount; + String reactionsId = "reactions" + currentAccount; String otherId = "other" + currentAccount; for (int a = 0, N = list.size(); a < N; a++) { String id = list.get(a).getId(); @@ -3360,17 +3439,19 @@ public class NotificationsController extends BaseController { groupsId = null; } else if (storiesId != null && storiesId.equals(id)) { storiesId = null; + } else if (reactionsId != null && reactionsId.equals(id)) { + reactionsId = null; } else if (privateId != null && privateId.equals(id)) { privateId = null; } else if (otherId != null && otherId.equals(id)) { otherId = null; } - if (channelsId == null && storiesId == null && groupsId == null && privateId == null && otherId == null) { + if (channelsId == null && storiesId == null && reactionsId == null && groupsId == null && privateId == null && otherId == null) { break; } } - if (channelsId != null || groupsId != null || storiesId != null || privateId != null || otherId != null) { + if (channelsId != null || groupsId != null || reactionsId != null || storiesId != null || privateId != null || otherId != null) { TLRPC.User user = getMessagesController().getUser(getUserConfig().getClientUserId()); if (user == null) { getUserConfig().getCurrentUser(); @@ -3390,7 +3471,10 @@ public class NotificationsController extends BaseController { channelGroups.add(new NotificationChannelGroup(groupsId, LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups) + userName)); } if (storiesId != null) { - channelGroups.add(new NotificationChannelGroup(storiesId, LocaleController.getString("NotificationsStories", R.string.NotificationsStories) + userName)); + channelGroups.add(new NotificationChannelGroup(storiesId, LocaleController.getString(R.string.NotificationsStories) + userName)); + } + if (reactionsId != null) { + channelGroups.add(new NotificationChannelGroup(reactionsId, LocaleController.getString(R.string.NotificationsReactions) + userName)); } if (privateId != null) { channelGroups.add(new NotificationChannelGroup(privateId, LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats) + userName)); @@ -3428,6 +3512,9 @@ public class NotificationsController extends BaseController { } else if (type == TYPE_STORIES) { groupId = "stories" + currentAccount; overwriteKey = "overwrite_stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + groupId = "reactions" + currentAccount; + overwriteKey = "overwrite_reactions"; } else { groupId = "private" + currentAccount; overwriteKey = "overwrite_private"; @@ -3453,6 +3540,8 @@ public class NotificationsController extends BaseController { key = isInApp ? "groups_ia" : "groups"; } else if (type == TYPE_STORIES) { key = isInApp ? "stories_ia" : "stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + key = isInApp ? "reactions_ia" : "reactions"; } else { key = isInApp ? "private_ia" : "private"; } @@ -3511,6 +3600,9 @@ public class NotificationsController extends BaseController { if (!isInApp) { if (type == TYPE_STORIES) { editor.putBoolean("EnableAllStories", false); + } else if (type == TYPE_REACTIONS_MESSAGES) { + editor.putBoolean("EnableReactionsMessages", true); + editor.putBoolean("EnableReactionsStories", true); } else { editor.putInt(getGlobalNotificationsKey(type), Integer.MAX_VALUE); } @@ -3541,6 +3633,9 @@ public class NotificationsController extends BaseController { if (isDefault) { if (type == TYPE_STORIES) { editor.putBoolean("EnableAllStories", true); + } else if (type == TYPE_REACTIONS_MESSAGES) { + editor.putBoolean("EnableReactionsMessages", true); + editor.putBoolean("EnableReactionsStories", true); } else { editor.putInt(getGlobalNotificationsKey(type), 0); } @@ -3550,6 +3645,8 @@ public class NotificationsController extends BaseController { editor.putInt("priority_group", priority); } else if (type == TYPE_STORIES) { editor.putInt("priority_stories", priority); + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + editor.putInt("priority_react", priority); } else { editor.putInt("priority_messages", priority); } @@ -3578,6 +3675,8 @@ public class NotificationsController extends BaseController { editor.putInt("vibrate_group", vibrate ? 0 : 2); } else if (type == TYPE_STORIES) { editor.putInt("vibrate_stories", vibrate ? 0 : 2); + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + editor.putInt("vibrate_react", vibrate ? 0 : 2); } else { editor.putInt("vibrate_messages", vibrate ? 0 : 2); } @@ -3600,6 +3699,8 @@ public class NotificationsController extends BaseController { editor.putInt("GroupLed", channelLedColor); } else if (type == TYPE_STORIES) { editor.putInt("StoriesLed", channelLedColor); + } else if (type == TYPE_REACTIONS_STORIES || type == TYPE_REACTIONS_MESSAGES) { + editor.putInt("ReactionsLed", channelLedColor); } else { editor.putInt("MessagesLed", channelLedColor); } @@ -3816,7 +3917,7 @@ public class NotificationsController extends BaseController { int notifyOverride = getNotifyOverride(preferences, override_dialog_id, topicId); boolean value; if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialog_id, isChannel); + value = isGlobalNotificationsEnabled(dialog_id, isChannel, lastMessageObject.isReactionPush, lastMessageObject.isReactionPush); } else { value = notifyOverride != 2; } @@ -3846,6 +3947,9 @@ public class NotificationsController extends BaseController { } else { name = chatName; } + if (lastMessageObject != null && (lastMessageObject.isReactionPush || lastMessageObject.isStoryReactionPush) && !preferences.getBoolean("EnableReactionsPreview", true)) { + name = LocaleController.getString("NotificationHiddenName", R.string.NotificationHiddenName); + } String detailText; if (UserConfig.getActivatedAccountsCount() > 1) { @@ -4001,7 +4105,19 @@ public class NotificationsController extends BaseController { } boolean vibrateOnlyIfSilent = false; - if (chatId != 0) { + if (lastMessageObject != null && (lastMessageObject.isReactionPush || lastMessageObject.isStoryReactionPush)) { + long soundDocumentId = preferences.getLong("ReactionSoundDocId", 0); + if (soundDocumentId != 0) { + isInternalSoundFile = true; + soundPath = getMediaDataController().ringtoneDataStore.getSoundPath(soundDocumentId); + } else { + soundPath = preferences.getString("ReactionSoundPath", defaultPath); + } + vibrate = preferences.getInt("vibrate_react", 0); + importance = preferences.getInt("priority_react", 1); + ledColor = preferences.getInt("ReactionsLed", 0xff0000ff); + chatType = lastMessageObject.isStoryReactionPush ? TYPE_REACTIONS_STORIES : TYPE_REACTIONS_MESSAGES; + } else if (chatId != 0) { if (isChannel) { long soundDocumentId = preferences.getLong("ChannelSoundDocId", 0); if (soundDocumentId != 0) { @@ -4096,7 +4212,9 @@ public class NotificationsController extends BaseController { intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - if (lastMessageObject.isStoryPush) { + if (lastMessageObject.isStoryReactionPush) { + intent.putExtra("storyId", Math.abs(lastMessageObject.getId())); + } else if (lastMessageObject.isStoryPush) { long[] peerIds = new long[storyPushMessages.size()]; for (int i = 0; i < storyPushMessages.size(); ++i) { peerIds[i] = storyPushMessages.get(i).dialogId; @@ -4159,6 +4277,9 @@ public class NotificationsController extends BaseController { if (lastMessageObject.isStoryPush) { dismissIntent.putExtra("story", true); } + if (lastMessageObject.isStoryReactionPush) { + dismissIntent.putExtra("storyReaction", true); + } mBuilder.setDeleteIntent(PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 1, dismissIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)); } catch (Throwable e) { FileLog.e(e); @@ -4342,6 +4463,8 @@ public class NotificationsController extends BaseController { editor.putString("GlobalSound", ringtoneName); } else if (chatType == TYPE_STORIES) { editor.putString("StoriesSound", ringtoneName); + } else if (chatType == TYPE_REACTIONS_MESSAGES || chatType == TYPE_REACTIONS_STORIES) { + editor.putString("ReactionSound", ringtoneName); } if (chatType == TYPE_CHANNEL) { editor.putString("ChannelSoundPath", newSound); @@ -4351,6 +4474,8 @@ public class NotificationsController extends BaseController { editor.putString("GlobalSoundPath", newSound); } else if (chatType == TYPE_STORIES) { editor.putString("StoriesSoundPath", newSound); + } else if (chatType == TYPE_REACTIONS_MESSAGES || chatType == TYPE_REACTIONS_STORIES) { + editor.putString("ReactionSound", newSound); } getNotificationsController().deleteNotificationChannelGlobalInternal(chatType, -1); } else { @@ -4527,7 +4652,7 @@ public class NotificationsController extends BaseController { photoPath = user.photo.photo_small; } } else if (!DialogObject.isEncryptedDialog(dialogId)) { - canReply = (lastMessageObject != null && !lastMessageObject.isReactionPush) && dialogId != 777000; + canReply = (lastMessageObject != null && !lastMessageObject.isReactionPush && !lastMessageObject.isStoryReactionPush) && dialogId != 777000; if (DialogObject.isUserDialog(dialogId)) { user = getMessagesController().getUser(dialogId); if (user == null) { @@ -4605,6 +4730,11 @@ public class NotificationsController extends BaseController { name = LocaleController.getString("SecretChatName", R.string.SecretChatName); photoPath = null; } + if (lastMessageObject != null && lastMessageObject.isStoryReactionPush && !preferences.getBoolean("EnableReactionsPreview", true)) { + canReply = false; + name = LocaleController.getString("NotificationHiddenChatName", R.string.NotificationHiddenChatName); + photoPath = null; + } if (waitingForPasscode) { if (DialogObject.isChatDialog(dialogId)) { @@ -4964,7 +5094,9 @@ public class NotificationsController extends BaseController { intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addCategory(Intent.CATEGORY_LAUNCHER); - if (dialogKey.story) { + if (lastMessageObject != null && lastMessageObject.isStoryReactionPush) { + intent.putExtra("storyId", Math.abs(lastMessageObject.getId())); + } else if (dialogKey.story) { long[] peerIds = new long[storyPushMessages.size()]; for (int i = 0; i < storyPushMessages.size(); ++i) { peerIds[i] = storyPushMessages.get(i).dialogId; @@ -5068,7 +5200,7 @@ public class NotificationsController extends BaseController { if (wearReplyAction != null) { builder.addAction(wearReplyAction); } - if (!waitingForPasscode && !dialogKey.story) { + if (!waitingForPasscode && !dialogKey.story && (lastMessageObject == null || !lastMessageObject.isStoryReactionPush)) { builder.addAction(readAction); } if (sortedDialogs.size() == 1 && !TextUtils.isEmpty(summary) && !dialogKey.story) { @@ -5395,7 +5527,7 @@ public class NotificationsController extends BaseController { SharedPreferences.Editor editor = preferences.edit(); TLRPC.Dialog dialog = MessagesController.getInstance(UserConfig.selectedAccount).dialogs_dict.get(dialog_id); if (setting == SETTING_MUTE_UNMUTE) { - boolean defaultEnabled = isGlobalNotificationsEnabled(dialog_id); + boolean defaultEnabled = isGlobalNotificationsEnabled(dialog_id, false, false); if (defaultEnabled) { editor.remove("notify2_" + NotificationsController.getSharedPrefKey(dialog_id, topicId)); } else { @@ -5513,9 +5645,36 @@ public class NotificationsController extends BaseController { public final static int TYPE_PRIVATE = 1; public final static int TYPE_CHANNEL = 2; public final static int TYPE_STORIES = 3; + public final static int TYPE_REACTIONS_MESSAGES = 4; + public final static int TYPE_REACTIONS_STORIES = 5; public void updateServerNotificationsSettings(int type) { SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); + if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + TLRPC.TL_account_setReactionsNotifySettings req = new TLRPC.TL_account_setReactionsNotifySettings(); + req.settings = new TLRPC.TL_reactionsNotifySettings(); + if (preferences.getBoolean("EnableReactionsMessages", true)) { + req.settings.flags |= 1; + if (preferences.getBoolean("EnableReactionsMessagesContacts", false)) { + req.settings.messages_notify_from = new TLRPC.TL_reactionNotificationsFromContacts(); + } else { + req.settings.messages_notify_from = new TLRPC.TL_reactionNotificationsFromAll(); + } + } + if (preferences.getBoolean("EnableReactionsStories", true)) { + req.settings.flags |= 2; + if (preferences.getBoolean("EnableReactionsStoriesContacts", false)) { + req.settings.stories_notify_from = new TLRPC.TL_reactionNotificationsFromContacts(); + } else { + req.settings.stories_notify_from = new TLRPC.TL_reactionNotificationsFromAll(); + } + } + req.settings.show_previews = preferences.getBoolean("EnableReactionsPreview", true); + req.settings.sound = getInputSound(preferences, "ReactionSound", "ReactionSoundDocId", "ReactionSoundPath"); + getConnectionsManager().sendRequest(req, (response, error) -> { }); + return; + } + TLRPC.TL_account_updateNotifySettings req = new TLRPC.TL_account_updateNotifySettings(); req.settings = new TLRPC.TL_inputPeerNotifySettings(); req.settings.flags = 5; @@ -5576,13 +5735,17 @@ public class NotificationsController extends BaseController { } } - public boolean isGlobalNotificationsEnabled(long dialogId) { - return isGlobalNotificationsEnabled(dialogId, null); + public boolean isGlobalNotificationsEnabled(long dialogId, boolean isReaction, boolean isStoryReaction) { + return isGlobalNotificationsEnabled(dialogId, null, isReaction, isStoryReaction); } - public boolean isGlobalNotificationsEnabled(long dialogId, Boolean forceChannel) { + public boolean isGlobalNotificationsEnabled(long dialogId, Boolean forceChannel, boolean isReaction, boolean isStoryReaction) { int type; - if (DialogObject.isChatDialog(dialogId)) { + if (isReaction) { + type = TYPE_REACTIONS_MESSAGES; + } else if (isStoryReaction) { + type = TYPE_REACTIONS_STORIES; + } else if (DialogObject.isChatDialog(dialogId)) { if (forceChannel != null) { if (forceChannel) { type = TYPE_CHANNEL; @@ -5604,6 +5767,12 @@ public class NotificationsController extends BaseController { } public boolean isGlobalNotificationsEnabled(int type) { + if (type == TYPE_REACTIONS_MESSAGES) { + return getAccountInstance().getNotificationsSettings().getBoolean("EnableReactionsMessages", true); + } + if (type == TYPE_REACTIONS_STORIES) { + return getAccountInstance().getNotificationsSettings().getBoolean("EnableReactionsStories", true); + } if (type == TYPE_STORIES) { return getAccountInstance().getNotificationsSettings().getBoolean("EnableAllStories", true); } @@ -5631,7 +5800,7 @@ public class NotificationsController extends BaseController { if (mute) { NotificationsController.getInstance(currentAccount).muteUntil(dialog_id, topicId, Integer.MAX_VALUE); } else { - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialog_id); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialog_id, false, false); boolean override = topicId != 0; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); SharedPreferences.Editor editor = preferences.edit(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java index 04d171f73..6507ffec1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java @@ -1,6 +1,8 @@ package org.telegram.messenger; import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_MESSAGES; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_STORIES; import android.content.SharedPreferences; @@ -208,6 +210,10 @@ public class NotificationsSettingsFacade { soundPref = "GlobalSound"; soundDocPref = "GlobalSoundDocId"; soundPathPref = "GlobalSoundPath"; + } else if (globalType == TYPE_REACTIONS_MESSAGES || globalType == TYPE_REACTIONS_STORIES) { + soundPref = "ReactionSound"; + soundDocPref = "ReactionSoundDocId"; + soundPathPref = "ReactionSoundPath"; } else { soundPref = "ChannelSound"; soundDocPref = "ChannelSoundDocId"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index 277d24edc..41be2f1ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -373,6 +373,8 @@ public class PushListenerController { int msg_id; if (custom.has("msg_id")) { msg_id = custom.getInt("msg_id"); + } else if (custom.has("story_id")) { + msg_id = custom.getInt("story_id"); } else { msg_id = 0; } @@ -1199,6 +1201,9 @@ public class PushListenerController { } if (messageText != null) { TLRPC.TL_message messageOwner = new TLRPC.TL_message(); + if (loc_key.startsWith("REACT_STORY") && msg_id > 0) { + msg_id = -msg_id; + } messageOwner.id = msg_id; messageOwner.random_id = random_id; messageOwner.message = message1 != null ? message1 : messageText; @@ -1243,7 +1248,8 @@ public class PushListenerController { messageObject.messageOwner.reply_to.forum_topic = true; messageObject.messageOwner.reply_to.reply_to_top_id = topicId; } - messageObject.isReactionPush = loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_"); + messageObject.isStoryReactionPush = loc_key.startsWith("REACT_STORY"); + messageObject.isReactionPush = !messageObject.isStoryReactionPush && (loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_")); messageObject.isStoryPush = loc_key.equals("STORY_NOTEXT") || loc_key.equals("STORY_HIDDEN_AUTHOR"); messageObject.isStoryMentionPush = loc_key.equals("MESSAGE_STORY_MENTION"); messageObject.isStoryPushHidden = loc_key.equals("STORY_HIDDEN_AUTHOR"); @@ -1288,107 +1294,117 @@ public class PushListenerController { private static String getReactedText(String loc_key, Object[] args) { switch (loc_key) { + case "REACT_HIDDEN": { + return LocaleController.formatString(R.string.PushReactHidden, args); + } case "REACT_TEXT": { - return LocaleController.formatString("PushReactText", R.string.PushReactText, args); + return LocaleController.formatString(R.string.PushReactText, args); } case "REACT_NOTEXT": { - return LocaleController.formatString("PushReactNoText", R.string.PushReactNoText, args); + return LocaleController.formatString(R.string.PushReactNoText, args); } case "REACT_PHOTO": { - return LocaleController.formatString("PushReactPhoto", R.string.PushReactPhoto, args); + return LocaleController.formatString(R.string.PushReactPhoto, args); } case "REACT_VIDEO": { - return LocaleController.formatString("PushReactVideo", R.string.PushReactVideo, args); + return LocaleController.formatString(R.string.PushReactVideo, args); } case "REACT_ROUND": { - return LocaleController.formatString("PushReactRound", R.string.PushReactRound, args); + return LocaleController.formatString(R.string.PushReactRound, args); } case "REACT_DOC": { - return LocaleController.formatString("PushReactDoc", R.string.PushReactDoc, args); + return LocaleController.formatString(R.string.PushReactDoc, args); } case "REACT_STICKER": { - return LocaleController.formatString("PushReactSticker", R.string.PushReactSticker, args); + return LocaleController.formatString(R.string.PushReactSticker, args); } case "REACT_AUDIO": { - return LocaleController.formatString("PushReactAudio", R.string.PushReactAudio, args); + return LocaleController.formatString(R.string.PushReactAudio, args); } case "REACT_CONTACT": { - return LocaleController.formatString("PushReactContect", R.string.PushReactContect, args); + return LocaleController.formatString(R.string.PushReactContect, args); } case "REACT_GEO": { - return LocaleController.formatString("PushReactGeo", R.string.PushReactGeo, args); + return LocaleController.formatString(R.string.PushReactGeo, args); } case "REACT_GEOLIVE": { - return LocaleController.formatString("PushReactGeoLocation", R.string.PushReactGeoLocation, args); + return LocaleController.formatString(R.string.PushReactGeoLocation, args); } case "REACT_POLL": { - return LocaleController.formatString("PushReactPoll", R.string.PushReactPoll, args); + return LocaleController.formatString(R.string.PushReactPoll, args); } case "REACT_QUIZ": { - return LocaleController.formatString("PushReactQuiz", R.string.PushReactQuiz, args); + return LocaleController.formatString(R.string.PushReactQuiz, args); } case "REACT_GAME": { - return LocaleController.formatString("PushReactGame", R.string.PushReactGame, args); + return LocaleController.formatString(R.string.PushReactGame, args); } case "REACT_INVOICE": { - return LocaleController.formatString("PushReactInvoice", R.string.PushReactInvoice, args); + return LocaleController.formatString(R.string.PushReactInvoice, args); } case "REACT_GIF": { - return LocaleController.formatString("PushReactGif", R.string.PushReactGif, args); + return LocaleController.formatString(R.string.PushReactGif, args); } case "REACT_GIVEAWAY": { - return LocaleController.formatString("NotificationReactGiveaway", R.string.NotificationReactGiveaway, args); + return LocaleController.formatString(R.string.NotificationReactGiveaway, args); } case "CHAT_REACT_GIVEAWAY": { - return LocaleController.formatString("NotificationChatReactGiveaway", R.string.NotificationChatReactGiveaway, args); + return LocaleController.formatString(R.string.NotificationChatReactGiveaway, args); } case "CHAT_REACT_TEXT": { - return LocaleController.formatString("PushChatReactText", R.string.PushChatReactText, args); + return LocaleController.formatString(R.string.PushChatReactText, args); } case "CHAT_REACT_NOTEXT": { - return LocaleController.formatString("PushChatReactNotext", R.string.PushChatReactNotext, args); + return LocaleController.formatString(R.string.PushChatReactNotext, args); } case "CHAT_REACT_PHOTO": { - return LocaleController.formatString("PushChatReactPhoto", R.string.PushChatReactPhoto, args); + return LocaleController.formatString(R.string.PushChatReactPhoto, args); } case "CHAT_REACT_VIDEO": { - return LocaleController.formatString("PushChatReactVideo", R.string.PushChatReactVideo, args); + return LocaleController.formatString(R.string.PushChatReactVideo, args); } case "CHAT_REACT_ROUND": { - return LocaleController.formatString("PushChatReactRound", R.string.PushChatReactRound, args); + return LocaleController.formatString(R.string.PushChatReactRound, args); } case "CHAT_REACT_DOC": { - return LocaleController.formatString("PushChatReactDoc", R.string.PushChatReactDoc, args); + return LocaleController.formatString(R.string.PushChatReactDoc, args); } case "CHAT_REACT_STICKER": { - return LocaleController.formatString("PushChatReactSticker", R.string.PushChatReactSticker, args); + return LocaleController.formatString(R.string.PushChatReactSticker, args); } case "CHAT_REACT_AUDIO": { - return LocaleController.formatString("PushChatReactAudio", R.string.PushChatReactAudio, args); + return LocaleController.formatString(R.string.PushChatReactAudio, args); } case "CHAT_REACT_CONTACT": { - return LocaleController.formatString("PushChatReactContact", R.string.PushChatReactContact, args); + return LocaleController.formatString(R.string.PushChatReactContact, args); } case "CHAT_REACT_GEO": { - return LocaleController.formatString("PushChatReactGeo", R.string.PushChatReactGeo, args); + return LocaleController.formatString(R.string.PushChatReactGeo, args); } case "CHAT_REACT_GEOLIVE": { - return LocaleController.formatString("PushChatReactGeoLive", R.string.PushChatReactGeoLive, args); + return LocaleController.formatString(R.string.PushChatReactGeoLive, args); } case "CHAT_REACT_POLL": { - return LocaleController.formatString("PushChatReactPoll", R.string.PushChatReactPoll, args); + return LocaleController.formatString(R.string.PushChatReactPoll, args); } case "CHAT_REACT_QUIZ": { - return LocaleController.formatString("PushChatReactQuiz", R.string.PushChatReactQuiz, args); + return LocaleController.formatString(R.string.PushChatReactQuiz, args); } case "CHAT_REACT_GAME": { - return LocaleController.formatString("PushChatReactGame", R.string.PushChatReactGame, args); + return LocaleController.formatString(R.string.PushChatReactGame, args); } case "CHAT_REACT_INVOICE": { - return LocaleController.formatString("PushChatReactInvoice", R.string.PushChatReactInvoice, args); + return LocaleController.formatString(R.string.PushChatReactInvoice, args); } case "CHAT_REACT_GIF": { - return LocaleController.formatString("PushChatReactGif", R.string.PushChatReactGif, args); + return LocaleController.formatString(R.string.PushChatReactGif, args); + } + /* stories */ + case "REACT_STORY": { + return LocaleController.formatString(R.string.PushReactStory, args); + } + case "REACT_STORY_HIDDEN": { + return LocaleController.formatString(R.string.PushReactStoryHidden, args); } } return null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index 2ee054124..6603f4083 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -760,6 +760,7 @@ public class SecretChatHelper extends BaseController { AndroidUtilities.runOnUIThread(() -> { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, false); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, false); getSendMessagesHelper().processSentMessage(newMsgObj.id); getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id, false); }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index d531cb84d..f2a113f37 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -961,7 +961,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else if (message.type == 1) { if (media.file == null) { media.file = file; - if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { + if (media.thumb == null && message.photoSize != null && message.photoSize.location != null && (message.obj == null || message.obj.videoEditedInfo == null || !message.obj.videoEditedInfo.isSticker)) { performSendDelayedMessage(message); } else { performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); @@ -2322,6 +2322,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe newMsgObj1.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getMediaDataController().increasePeerRaiting(peer); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, message.id, message, peer, 0L, existFlags, scheduleDate != 0); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, message.id, message, peer, 0L, existFlags, scheduleDate != 0); processSentMessage(oldId); removeFromSendingMessages(oldId, scheduleDate != 0); }); @@ -2748,7 +2749,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe delayedMessage.originalPath = originalPath; delayedMessage.type = 2; delayedMessage.obj = messageObject; - if (!document.thumbs.isEmpty()) { + if (!document.thumbs.isEmpty() && (videoEditedInfo == null || !videoEditedInfo.isSticker)) { TLRPC.PhotoSize photoSize = document.thumbs.get(0); if (!(photoSize instanceof TLRPC.TL_photoStrippedSize)) { delayedMessage.photoSize = photoSize; @@ -2966,7 +2967,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe return waitingForVote.get(key); } - public int sendVote(final MessageObject messageObject, final ArrayList answers, final Runnable finishRunnable) { + public int sendVote(final MessageObject messageObject, final ArrayList answers, final Runnable finishRunnable) { if (messageObject == null) { return 0; } @@ -2981,7 +2982,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (answers != null) { options = new byte[answers.size()]; for (int a = 0; a < answers.size(); a++) { - TLRPC.TL_pollAnswer answer = answers.get(a); + TLRPC.PollAnswer answer = answers.get(a); req.options.add(answer.option); options[a] = answer.option[0]; } @@ -5172,7 +5173,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } putToUploadingMessages(message.obj); } else { - String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg"; + String ext = "jpg"; + if (message.obj != null && message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.isSticker) { + ext = "webp"; + } + String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + "." + ext; putToDelayedMessages(location, message); getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto); putToUploadingMessages(message.obj); @@ -5860,6 +5865,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe getStatsController().incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); getMessagesStorage().getStorageQueue().postRunnable(() -> { int mode = scheduled ? ChatActivity.MODE_SCHEDULED : 0; if (newMsgObj.quick_reply_shortcut_id != 0 || newMsgObj.quick_reply_shortcut != null) { @@ -5870,6 +5876,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe AndroidUtilities.runOnUIThread(() -> { getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); processSentMessage(oldId); removeFromSendingMessages(oldId, scheduled); }); @@ -6197,6 +6204,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe }); } else { getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); getMessagesStorage().getStorageQueue().postRunnable(() -> { int mode = scheduled ? ChatActivity.MODE_SCHEDULED : 0; if (newMsgObj.quick_reply_shortcut_id != 0 || newMsgObj.quick_reply_shortcut != null) { @@ -6207,6 +6215,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe AndroidUtilities.runOnUIThread(() -> { getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); processSentMessage(oldId); removeFromSendingMessages(oldId, scheduled); }); @@ -6419,7 +6428,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe newMsg.media.document.size = sentMessage.media.document.size; newMsg.media.document.mime_type = sentMessage.media.document.mime_type; - if ((sentMessage.flags & TLRPC.MESSAGE_FLAG_FWD) == 0 && MessageObject.isOut(sentMessage) && !MessageObject.isQuickReply(sentMessage)) { + if ((sentMessage.flags & TLRPC.MESSAGE_FLAG_FWD) == 0 && (MessageObject.isOut(sentMessage) || sentMessage.dialog_id == getUserConfig().getClientUserId()) && !MessageObject.isQuickReply(sentMessage)) { if (MessageObject.isNewGifDocument(sentMessage.media.document)) { boolean save; if (MessageObject.isDocumentHasAttachedStickers(sentMessage.media.document)) { @@ -8162,7 +8171,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe TLRPC.PhotoSize size = null; if (thumb != null) { int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight()); - size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted); + size = ImageLoader.scaleAndSaveImage(null, thumb, videoEditedInfo != null && videoEditedInfo.isSticker ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.JPEG, false, side, side, side > 90 ? 80 : 55, isEncrypted, 0, 0, false); if (size != null && size.location != null) { thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 16a28cac4..52b2c591d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -254,7 +254,7 @@ public class SharedConfig { public static boolean forceDisableTabletMode; public static boolean updateStickersOrderOnSend = true; public static boolean bigCameraForRound; - public static boolean useCamera2; + public static Boolean useCamera2Force; public static boolean useSurfaceInStories; public static boolean photoViewerBlur = true; public static boolean payByInvoice; @@ -643,7 +643,7 @@ public class SharedConfig { updateStickersOrderOnSend = preferences.getBoolean("updateStickersOrderOnSend", true); dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0); bigCameraForRound = preferences.getBoolean("bigCameraForRound", false); - useCamera2 = preferences.getBoolean("useCamera2", BuildVars.DEBUG_VERSION); + useCamera2Force = !preferences.contains("useCamera2Force") ? null : preferences.getBoolean("useCamera2Force", false); useSurfaceInStories = preferences.getBoolean("useSurfaceInStories", Build.VERSION.SDK_INT >= 30); payByInvoice = preferences.getBoolean("payByInvoice", false); photoViewerBlur = preferences.getBoolean("photoViewerBlur", true); @@ -1739,10 +1739,14 @@ public class SharedConfig { .apply(); } - public static void toggleUseCamera2() { + public static boolean isUsingCamera2(int currentAccount) { + return useCamera2Force == null ? !MessagesController.getInstance(currentAccount).androidDisableRoundCamera2 : useCamera2Force; + } + + public static void toggleUseCamera2(int currentAccount) { ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) .edit() - .putBoolean("useCamera2", useCamera2 = !useCamera2) + .putBoolean("useCamera2", useCamera2Force = !isUsingCamera2(currentAccount)) .apply(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java index 71836aab0..fa491caf3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java @@ -98,6 +98,7 @@ public class TranslateController extends BaseController { messageObject != null && messageObject.messageOwner != null && !messageObject.isOutOwner() && !messageObject.isRestrictedMessage && + !messageObject.isSponsored() && ( messageObject.type == MessageObject.TYPE_TEXT || messageObject.type == MessageObject.TYPE_VIDEO || @@ -509,7 +510,10 @@ public class TranslateController extends BaseController { final MessageObject finalMessageObject = messageObject; if (finalMessageObject.messageOwner.translatedText == null || !language.equals(finalMessageObject.messageOwner.translatedToLanguage)) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageTranslating, finalMessageObject); - pushToTranslate(finalMessageObject, language, (text, lang) -> { + pushToTranslate(finalMessageObject, language, (id, text, lang) -> { + if (finalMessageObject.getId() != id) { + FileLog.e("wtf, asked to translate " + finalMessageObject.getId() + " but got " + id + "!"); + } finalMessageObject.messageOwner.translatedToLanguage = lang; finalMessageObject.messageOwner.translatedText = text; if (keepReply) { @@ -715,7 +719,7 @@ public class TranslateController extends BaseController { Runnable runnable; ArrayList messageIds = new ArrayList<>(); ArrayList messageTexts = new ArrayList<>(); - ArrayList> callbacks = new ArrayList<>(); + ArrayList> callbacks = new ArrayList<>(); String language; int delay = GROUPING_TRANSLATIONS_TIMEOUT; @@ -727,9 +731,9 @@ public class TranslateController extends BaseController { private void pushToTranslate( MessageObject message, String language, - Utilities.Callback2 callback + Utilities.Callback3 callback ) { - if (message == null || callback == null) { + if (message == null || message.getId() < 0 || callback == null) { return; } @@ -779,6 +783,7 @@ public class TranslateController extends BaseController { source.text = message.messageOwner.message; source.entities = message.messageOwner.entities; } + FileLog.d("pending translation +" + message.getId() + " message"); pendingTranslation.messageTexts.add(source); pendingTranslation.callbacks.add(callback); pendingTranslation.language = language; @@ -803,7 +808,7 @@ public class TranslateController extends BaseController { final int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { final ArrayList ids; - final ArrayList> callbacks; + final ArrayList> callbacks; final ArrayList texts; synchronized (TranslateController.this) { ids = pendingTranslation1.messageIds; @@ -814,14 +819,14 @@ public class TranslateController extends BaseController { ArrayList translated = ((TLRPC.TL_messages_translateResult) res).result; final int count = Math.min(callbacks.size(), translated.size()); for (int i = 0; i < count; ++i) { - callbacks.get(i).run(TranslateAlert2.preprocess(texts.get(i), translated.get(i)), pendingTranslation1.language); + callbacks.get(i).run(ids.get(i), TranslateAlert2.preprocess(texts.get(i), translated.get(i)), pendingTranslation1.language); } } else if (err != null && "TO_LANG_INVALID".equals(err.text)) { toggleTranslatingDialog(dialogId, false); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_ERROR, LocaleController.getString("TranslationFailedAlert2", R.string.TranslationFailedAlert2)); } else { for (int i = 0; i < callbacks.size(); ++i) { - callbacks.get(i).run(null, pendingTranslation1.language); + callbacks.get(i).run(ids.get(i), null, pendingTranslation1.language); } } synchronized (TranslateController.this) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 6dec98993..b6f521b29 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -159,7 +159,7 @@ public class UserConfig extends BaseController { editor.putBoolean("syncContacts", syncContacts); editor.putBoolean("suggestContacts", suggestContacts); editor.putBoolean("hasSecureData", hasSecureData); - editor.putBoolean("notificationsSettingsLoaded3", notificationsSettingsLoaded); + editor.putBoolean("notificationsSettingsLoaded4", notificationsSettingsLoaded); editor.putBoolean("notificationsSignUpSettingsLoaded", notificationsSignUpSettingsLoaded); editor.putLong("autoDownloadConfigLoadTime", autoDownloadConfigLoadTime); editor.putBoolean("hasValidDialogLoadIds", hasValidDialogLoadIds); @@ -302,7 +302,7 @@ public class UserConfig extends BaseController { syncContacts = preferences.getBoolean("syncContacts", true); suggestContacts = preferences.getBoolean("suggestContacts", true); hasSecureData = preferences.getBoolean("hasSecureData", false); - notificationsSettingsLoaded = preferences.getBoolean("notificationsSettingsLoaded3", false); + notificationsSettingsLoaded = preferences.getBoolean("notificationsSettingsLoaded4", false); notificationsSignUpSettingsLoaded = preferences.getBoolean("notificationsSignUpSettingsLoaded", false); autoDownloadConfigLoadTime = preferences.getLong("autoDownloadConfigLoadTime", 0); hasValidDialogLoadIds = preferences.contains("2dialogsLoadOffsetId") || preferences.getBoolean("hasValidDialogLoadIds", false); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 79b124382..0ab6bdc03 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -581,6 +581,10 @@ public class Utilities { public ReturnType run(T arg, T2 arg2, T3 arg3, T4 arg4, T5 arg5); } + public static interface IndexedConsumer { + void accept(T t, int index); + } + public static Value getOrDefault(HashMap map, Key key, Value defaultValue) { Value v = map.get(key); if (v == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java index af68fe0ea..a1e39af6e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java @@ -153,6 +153,7 @@ public class VideoEditedInfo { public float textViewHeight; public float textViewX; public float textViewY; + public boolean customTextView; public TLRPC.Document document; public Object parentObject; 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 4ec2e51a9..f7afa9da7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -317,7 +317,7 @@ public class Browser { String token = "autologin_token=" + URLEncoder.encode(AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController().autologinToken, "UTF-8"); String url = uri.toString(); int idx = url.indexOf("://"); - String path = idx >= 0 ? url.substring(idx + 3) : url; + String path = idx >= 0 && idx <= 5 && !url.substring(0, idx).contains(".") ? url.substring(idx + 3) : url; String fragment = uri.getEncodedFragment(); String finalPath = fragment == null ? path : path.substring(0, path.indexOf("#" + fragment)); if (finalPath.indexOf('?') >= 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java index 395655f06..bc37ca6d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java @@ -21,6 +21,7 @@ import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; +import android.util.Range; import android.util.Size; import android.util.SizeF; import android.view.Surface; @@ -475,6 +476,11 @@ public class Camera2Session { captureRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, isFront ? CameraMetadata.CONTROL_SCENE_MODE_NIGHT_PORTRAIT : CameraMetadata.CONTROL_SCENE_MODE_NIGHT); } + if (recordingVideo) { + captureRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range(30, 60)); + captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + } + if (sensorSize != null && Math.abs(currentZoom - 1f) >= 0.01f) { final int centerX = sensorSize.width() / 2; final int centerY = sensorSize.height() / 2; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java index 8623a979e..e219b761f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java @@ -42,8 +42,6 @@ import android.os.Looper; import android.os.Message; import android.os.VibrationEffect; import android.os.Vibrator; -import android.text.TextUtils; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.Surface; @@ -55,9 +53,6 @@ import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; -import androidx.interpolator.view.animation.FastOutSlowInInterpolator; - -import com.google.zxing.common.detector.MathUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -66,9 +61,9 @@ import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.video.MP4Builder; import org.telegram.messenger.video.MediaCodecVideoConvertor; @@ -121,7 +116,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private int focusAreaSize; private Drawable thumbDrawable; - private final boolean useCamera2 = false && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.useCamera2; + private final boolean useCamera2 = false && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.isUsingCamera2(UserConfig.selectedAccount); private final CameraSessionWrapper[] cameraSession = new CameraSessionWrapper[2]; private CameraSessionWrapper cameraSessionRecording; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java index 59198173b..c0f4007cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java @@ -292,9 +292,12 @@ public final class ExtendedDefaultDataSource implements DataSource { return encryptedFileDataSource; } + private FileStreamLoadOperation streamLoadOperation; private DataSource getStreamDataSource() { - FileStreamLoadOperation streamLoadOperation = new FileStreamLoadOperation(); - addListenersToDataSource(streamLoadOperation); + if (streamLoadOperation == null) { + streamLoadOperation = new FileStreamLoadOperation(); + addListenersToDataSource(streamLoadOperation); + } return streamLoadOperation; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java index 6b5b5f079..9708476cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java @@ -53,7 +53,7 @@ public class MediaCodecVideoConvertor { public boolean convertVideo(ConvertVideoParams convertVideoParams) { if (convertVideoParams.isSticker) { - return WebmEncoder.convert(convertVideoParams); + return WebmEncoder.convert(convertVideoParams, 0); } this.callback = convertVideoParams.callback; return convertVideoInternal(convertVideoParams, false, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java index 3dce8ec35..7ff253b8f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java @@ -15,6 +15,7 @@ import android.opengl.GLES20; import android.opengl.GLUtils; import android.os.Build; import android.text.Layout; +import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; @@ -70,10 +71,12 @@ public class WebmEncoder { public static native void stop(long ptr); - public static boolean convert(MediaCodecVideoConvertor.ConvertVideoParams params) { + public static boolean convert(MediaCodecVideoConvertor.ConvertVideoParams params, int triesLeft) { final int W = params.resultWidth; final int H = params.resultHeight; + final long maxFileSize = 255 * 1024; + final long ptr = createEncoder(params.cacheFile.getAbsolutePath(), W, H, params.framerate, params.bitrate); if (ptr == 0) { return true; @@ -102,7 +105,7 @@ public class WebmEncoder { } if (params.callback != null) { - params.callback.didWriteData(params.cacheFile.length(), (float) frame / framesCount); + params.callback.didWriteData(Math.min(maxFileSize, params.cacheFile.length()), (float) frame / framesCount); } if (frame % 3 == 0 && params.callback != null) { @@ -119,11 +122,20 @@ public class WebmEncoder { } } - if (params.callback != null) { - params.callback.didWriteData(params.cacheFile.length(), 1f); + long fileSize = params.cacheFile.length(); + if (triesLeft > 0 && fileSize > maxFileSize) { + int oldBitrate = params.bitrate; + params.bitrate *= ((float) maxFileSize / fileSize) * .9f; + params.cacheFile.delete(); + FileLog.d("webm encoded too much, got " + fileSize + ", old bitrate = " + oldBitrate + " new bitrate = " + params.bitrate); + return convert(params, triesLeft - 1); } - FileLog.d("webm encoded to " + params.cacheFile + " with size=" + params.cacheFile.length()); + if (params.callback != null) { + params.callback.didWriteData(fileSize, 1f); + } + + FileLog.d("webm encoded to " + params.cacheFile + " with size=" + fileSize + " triesLeft=" + triesLeft); return error; } @@ -139,11 +151,17 @@ public class WebmEncoder { private final Paint clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); + private final Path clipPath; + public FrameDrawer(MediaCodecVideoConvertor.ConvertVideoParams params) { this.W = params.resultWidth; this.H = params.resultHeight; this.fps = params.framerate; + clipPath = new Path(); + RectF bounds = new RectF(0, 0, W, H); + clipPath.addRoundRect(bounds, W * .125f, H * .125f, Path.Direction.CW); + photo = BitmapFactory.decodeFile(params.videoPath); mediaEntities.addAll(params.mediaEntities); @@ -165,6 +183,8 @@ public class WebmEncoder { public void draw(Canvas canvas, int frame) { canvas.drawPaint(clearPaint); + canvas.save(); + canvas.clipPath(clipPath); if (photo != null) { canvas.drawBitmap(photo, 0, 0, null); } @@ -173,6 +193,7 @@ public class WebmEncoder { VideoEditedInfo.MediaEntity entity = mediaEntities.get(a); drawEntity(canvas, entity, entity.color, time); } + canvas.restore(); } private void drawEntity(Canvas canvas, VideoEditedInfo.MediaEntity entity, int textColor, long time) { @@ -231,7 +252,7 @@ public class WebmEncoder { editText.setTypeface(typeface); } editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, entity.fontSize); - SpannableString text = new SpannableString(entity.text); + CharSequence text = new SpannableString(entity.text); for (VideoEditedInfo.EmojiEntity e : entity.entities) { if (e.documentAbsolutePath == null) { continue; @@ -267,17 +288,19 @@ public class WebmEncoder { initStickerEntity(e.entity); } }; - text.setSpan(span, e.offset, e.offset + e.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + ((Spannable) text).setSpan(span, e.offset, e.offset + e.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - editText.setText(Emoji.replaceEmoji(text, editText.getPaint().getFontMetricsInt(), (int) (editText.getTextSize() * .8f), false)); - editText.setTextColor(entity.color); - CharSequence text2 = editText.getText(); - if (text2 instanceof Spanned) { - Emoji.EmojiSpan[] spans = ((Spanned) text2).getSpans(0, text2.length(), Emoji.EmojiSpan.class); - for (int i = 0; i < spans.length; ++i) { - spans[i].scale = .85f; + text = Emoji.replaceEmoji(text, editText.getPaint().getFontMetricsInt(), (int) (editText.getTextSize() * .8f), false); + if (text instanceof Spanned) { + Emoji.EmojiSpan[] spans = ((Spanned) text).getSpans(0, text.length(), Emoji.EmojiSpan.class); + if (spans != null) { + for (int i = 0; i < spans.length; ++i) { + spans[i].scale = .85f; + } } } + editText.setText(text); + editText.setTextColor(entity.color); int gravity; @@ -365,11 +388,11 @@ public class WebmEncoder { entity.bitmap = Bitmap.createBitmap(entity.W, entity.H, Bitmap.Config.ARGB_8888); entity.metadata = new int[3]; entity.ptr = RLottieDrawable.create(entity.text, null, entity.W, entity.H, entity.metadata, false, null, false, 0); - entity.framesPerDraw = entity.metadata[1] / fps; + entity.framesPerDraw = (float) entity.metadata[1] / fps; } else if ((entity.subType & 4) != 0) { entity.looped = false; entity.animatedFileDrawable = new AnimatedFileDrawable(new File(entity.text), true, 0, 0, null, null, null, 0, UserConfig.selectedAccount, true, 512, 512, null); - entity.framesPerDraw = entity.animatedFileDrawable.getFps() / fps; + entity.framesPerDraw = (float) entity.animatedFileDrawable.getFps() / fps; entity.currentFrame = 1; entity.animatedFileDrawable.getNextFrame(true); if (entity.type == VideoEditedInfo.MediaEntity.TYPE_ROUND) { @@ -445,12 +468,12 @@ public class WebmEncoder { if (bitmap != null) { entity.matrix.postScale(1f / bitmap.getWidth(), 1f / bitmap.getHeight()); } - if ((entity.subType & 2) != 0) { + if (entity.type != VideoEditedInfo.MediaEntity.TYPE_TEXT && (entity.subType & 2) != 0) { entity.matrix.postScale(-1, 1, .5f, .5f); } entity.matrix.postScale(entity.width * W, entity.height * H); entity.matrix.postTranslate(entity.x * W, entity.y * H); - entity.matrix.postRotate((float) (-entity.rotation / Math.PI * 180), (entity.x + entity.width) * W, (entity.x + entity.height) * H); + entity.matrix.postRotate((float) (-entity.rotation / Math.PI * 180), (entity.x + entity.width / 2f) * W, (entity.y + entity.height / 2f) * H); } Path path; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index c792f6d81..da6912baa 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -77,7 +77,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800; public static final int MESSAGE_FLAG_EDITED = 0x00008000; - public static final int LAYER = 177; + public static final int LAYER = 179; public static abstract class EmailVerifyPurpose extends TLObject { @@ -2819,33 +2819,59 @@ public class TLRPC { } } - public static class TL_pollAnswer extends TLObject { + public static class PollAnswer extends TLObject { public static final int constructor = 0x6ca9c2e9; - public String text; + public TL_textWithEntities text = new TL_textWithEntities(); public byte[] option; - public static TL_pollAnswer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_pollAnswer.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_pollAnswer", constructor)); - } else { - return null; - } + public static PollAnswer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + PollAnswer result = null; + switch (constructor) { + case TL_pollAnswer.constructor: + result = new TL_pollAnswer(); + break; + case TL_pollAnswer_layer178.constructor: + result = new TL_pollAnswer_layer178(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in JSONValue", constructor)); + } + if (result != null) { + result.readParams(stream, exception); } - TL_pollAnswer result = new TL_pollAnswer(); - result.readParams(stream, exception); return result; } + } + + public static class TL_pollAnswer extends PollAnswer { + public static final int constructor = 0xff16e2ca; public void readParams(AbstractSerializedData stream, boolean exception) { - text = stream.readString(exception); + text = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); option = stream.readByteArray(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeString(text); + text.serializeToStream(stream); + stream.writeByteArray(option); + } + } + + public static class TL_pollAnswer_layer178 extends TL_pollAnswer { + public static final int constructor = 0x6ca9c2e9; + + public void readParams(AbstractSerializedData stream, boolean exception) { + text = new TL_textWithEntities(); + text.text = stream.readString(exception); + option = stream.readByteArray(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(text == null ? "" : text.text); stream.writeByteArray(option); } } @@ -6827,6 +6853,7 @@ public class TLRPC { public int push_timeout; public int reset_available_period; public int reset_pending_date; + public String beginning; public boolean verifiedFirebase; //custom public static auth_SentCodeType TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -6859,6 +6886,12 @@ public class TLRPC { case 0xe57b1432: result = new TL_auth_sentCodeTypeFirebaseSms(); break; + case 0xa416ac81: + result = new TL_auth_sentCodeTypeSmsWord(); + break; + case 0xb37794af: + result = new TL_auth_sentCodeTypeSmsPhrase(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in auth_SentCodeType", constructor)); @@ -7042,6 +7075,44 @@ public class TLRPC { } } + public static class TL_auth_sentCodeTypeSmsWord extends auth_SentCodeType { + public static final int constructor = 0xa416ac81; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + beginning = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(beginning); + } + } + } + + public static class TL_auth_sentCodeTypeSmsPhrase extends auth_SentCodeType { + public static final int constructor = 0xb37794af; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + beginning = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(beginning); + } + } + } + public static abstract class messages_StickerSetInstallResult extends TLObject { public ArrayList sets = new ArrayList<>(); @@ -11541,9 +11612,6 @@ public class TLRPC { case 0xc9ee1d87: result = new TL_messages_sponsoredMessages(); break; - case 0x65a4c7d5: - result = new TL_messages_sponsoredMessagesLayer147(); - break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in messages_SponsoredMessages", constructor)); @@ -11564,80 +11632,6 @@ public class TLRPC { } } - public static class TL_messages_sponsoredMessagesLayer147 extends messages_SponsoredMessages { - public static final int constructor = 0xc9ee1d87; - - public void readParams(AbstractSerializedData stream, boolean 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++) { - TL_sponsoredMessage object = TL_sponsoredMessage.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); - 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_sponsoredMessages extends messages_SponsoredMessages { public static final int constructor = 0xc9ee1d87; @@ -12007,6 +12001,9 @@ public class TLRPC { case TL_webPageAttributeStory.constructor: result = new TL_webPageAttributeStory(); break; + case TL_webPageAttributeStickerSet.constructor: + result = new TL_webPageAttributeStickerSet(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in contacts_Contacts", constructor)); @@ -12045,6 +12042,49 @@ public class TLRPC { } } + public static class TL_webPageAttributeStickerSet extends WebPageAttribute { + public final static int constructor = 0x50cc03d3; + + public Peer peer; + public boolean emojis; + public boolean text_color; + public ArrayList stickers = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + emojis = (flags & 1) != 0; + text_color = (flags & 2) != 0; + 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++) { + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + stickers.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = emojis ? (flags | 1) : (flags &~ 1); + flags = text_color ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt32(0x1cb5c415); + int count = stickers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stickers.get(a).serializeToStream(stream); + } + } + } + public static class TL_webPageAttributeStory_layer162 extends TL_webPageAttributeStory { public static final int constructor = 0x939a4671; @@ -12788,6 +12828,7 @@ public class TLRPC { public boolean view_forum_as_messages; public boolean restricted_sponsored; public ChatReactions available_reactions; + public int reactions_limit; public TL_stories.PeerStories stories; public WallPaper wallpaper; public int boosts_applied; @@ -12803,9 +12844,15 @@ public class TLRPC { case TL_chatFull.constructor: result = new TL_chatFull(); break; + case TL_chatFull_layer177.constructor: + result = new TL_chatFull_layer177(); + break; case TL_channelFull.constructor: result = new TL_channelFull(); break; + case TL_channelFull_layer177.constructor: + result = new TL_channelFull_layer177(); + break; case TL_channelFull_layer176.constructor: result = new TL_channelFull_layer176(); break; @@ -14986,6 +15033,143 @@ public class TLRPC { } public static class TL_chatFull extends ChatFull { + public static final int constructor = 0x2633421b; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_set_username = (flags & 128) != 0; + has_scheduled = (flags & 256) != 0; + id = stream.readInt64(exception); + about = stream.readString(exception); + participants = ChatParticipants.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8192) != 0) { + exported_invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 8) != 0) { + 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++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + } + if ((flags & 64) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + if ((flags & 4096) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16384) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 65536) != 0) { + theme_emoticon = stream.readString(exception); + } + if ((flags & 131072) != 0) { + requests_pending = stream.readInt32(exception); + } + if ((flags & 131072) != 0) { + 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++) { + recent_requesters.add(stream.readInt64(exception)); + } + } + if ((flags & 262144) != 0) { + available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 1048576) != 0) { + reactions_limit = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_set_username ? (flags | 128) : (flags &~ 128); + flags = has_scheduled ? (flags | 256) : (flags &~ 256); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeString(about); + participants.serializeToStream(stream); + if ((flags & 4) != 0) { + chat_photo.serializeToStream(stream); + } + notify_settings.serializeToStream(stream); + if ((flags & 8192) != 0) { + exported_invite.serializeToStream(stream); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + } + if ((flags & 64) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + if ((flags & 4096) != 0) { + call.serializeToStream(stream); + } + if ((flags & 16384) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 32768) != 0) { + groupcall_default_join_as.serializeToStream(stream); + } + if ((flags & 65536) != 0) { + stream.writeString(theme_emoticon); + } + if ((flags & 131072) != 0) { + stream.writeInt32(requests_pending); + } + if ((flags & 131072) != 0) { + stream.writeInt32(0x1cb5c415); + int count = recent_requesters.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_requesters.get(a)); + } + } + if ((flags & 262144) != 0) { + available_reactions.serializeToStream(stream); + } + if ((flags & 1048576) != 0) { + stream.writeInt32(reactions_limit); + } + } + } + + public static class TL_chatFull_layer177 extends TL_chatFull { public static final int constructor = 0xc9d31138; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -15263,6 +15447,313 @@ public class TLRPC { } public static class TL_channelFull extends ChatFull { + public static final int constructor = 0xbbab348d; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_view_participants = (flags & 8) != 0; + can_set_username = (flags & 64) != 0; + can_set_stickers = (flags & 128) != 0; + hidden_prehistory = (flags & 1024) != 0; + can_set_location = (flags & 65536) != 0; + has_scheduled = (flags & 524288) != 0; + can_view_stats = (flags & 1048576) != 0; + blocked = (flags & 4194304) != 0; + flags2 = stream.readInt32(exception); + can_delete_channel = (flags2 & 1) != 0; + antispam = (flags2 & 2) != 0; + participants_hidden = (flags2 & 4) != 0; + translations_disabled = (flags2 & 8) != 0; + stories_pinned_available = (flags2 & 32) != 0; + view_forum_as_messages = (flags2 & 64) != 0; + restricted_sponsored = (flags2 & 2048) != 0; + can_view_revenue = (flags2 & 4096) != 0; + id = stream.readInt64(exception); + about = stream.readString(exception); + if ((flags & 1) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + admins_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + kicked_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + banned_count = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + online_count = stream.readInt32(exception); + } + read_inbox_max_id = stream.readInt32(exception); + read_outbox_max_id = stream.readInt32(exception); + unread_count = stream.readInt32(exception); + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8388608) != 0) { + exported_invite = ExportedChatInvite.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++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + if ((flags & 16) != 0) { + migrated_from_chat_id = stream.readInt64(exception); + } + if ((flags & 16) != 0) { + migrated_from_max_id = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 512) != 0) { + available_min_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + if ((flags & 16384) != 0) { + linked_chat_id = stream.readInt64(exception); + } + if ((flags & 32768) != 0) { + location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 131072) != 0) { + slowmode_seconds = stream.readInt32(exception); + } + if ((flags & 262144) != 0) { + slowmode_next_send_date = stream.readInt32(exception); + } + if ((flags & 4096) != 0) { + stats_dc = stream.readInt32(exception); + } + pts = stream.readInt32(exception); + if ((flags & 2097152) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16777216) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 33554432) != 0) { + 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++) { + pending_suggestions.add(stream.readString(exception)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 134217728) != 0) { + theme_emoticon = stream.readString(exception); + } + if ((flags & 268435456) != 0) { + requests_pending = stream.readInt32(exception); + } + if ((flags & 268435456) != 0) { + 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++) { + recent_requesters.add(stream.readInt64(exception)); + } + } + if ((flags & 536870912) != 0) { + default_send_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 1073741824) != 0) { + available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 8192) != 0) { + reactions_limit = stream.readInt32(exception); + } + if ((flags2 & 16) != 0) { + stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 128) != 0) { + wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 256) != 0) { + boosts_applied = stream.readInt32(exception); + } + if ((flags2 & 512) != 0) { + boosts_unrestrict = stream.readInt32(exception); + } + if ((flags2 & 1024) != 0) { + emojiset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_view_participants ? (flags | 8) : (flags &~ 8); + flags = can_set_username ? (flags | 64) : (flags &~ 64); + flags = can_set_stickers ? (flags | 128) : (flags &~ 128); + flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); + flags = can_set_location ? (flags | 65536) : (flags &~ 65536); + flags = has_scheduled ? (flags | 524288) : (flags &~ 524288); + flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); + flags = blocked ? (flags | 4194304) : (flags &~ 4194304); + stream.writeInt32(flags); + flags2 = can_delete_channel ? (flags2 | 1) : (flags2 &~ 1); + flags2 = antispam ? (flags2 | 2) : (flags2 &~ 2); + flags2 = participants_hidden ? (flags2 | 4) : (flags2 &~ 4); + flags2 = translations_disabled ? (flags2 | 8) : (flags2 &~ 8); + flags2 = stories_pinned_available ? (flags2 | 32) : (flags2 &~ 32); + flags2 = view_forum_as_messages ? (flags2 | 64) : (flags2 &~ 64); + flags2 = restricted_sponsored ? (flags2 | 2048) : (flags2 &~ 2048); + flags2 = can_view_revenue ? (flags2 | 4096) : (flags2 &~ 4096); + stream.writeInt32(flags2); + stream.writeInt64(id); + stream.writeString(about); + if ((flags & 1) != 0) { + stream.writeInt32(participants_count); + } + if ((flags & 2) != 0) { + stream.writeInt32(admins_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(kicked_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(banned_count); + } + if ((flags & 8192) != 0) { + stream.writeInt32(online_count); + } + stream.writeInt32(read_inbox_max_id); + stream.writeInt32(read_outbox_max_id); + stream.writeInt32(unread_count); + chat_photo.serializeToStream(stream); + notify_settings.serializeToStream(stream); + if ((flags & 8388608) != 0) { + exported_invite.serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt64(migrated_from_chat_id); + } + if ((flags & 16) != 0) { + stream.writeInt32(migrated_from_max_id); + } + if ((flags & 32) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 256) != 0) { + stickerset.serializeToStream(stream); + } + if ((flags & 512) != 0) { + stream.writeInt32(available_min_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + if ((flags & 16384) != 0) { + stream.writeInt64(linked_chat_id); + } + if ((flags & 32768) != 0) { + location.serializeToStream(stream); + } + if ((flags & 131072) != 0) { + stream.writeInt32(slowmode_seconds); + } + if ((flags & 262144) != 0) { + stream.writeInt32(slowmode_next_send_date); + } + if ((flags & 4096) != 0) { + stream.writeInt32(stats_dc); + } + stream.writeInt32(pts); + if ((flags & 2097152) != 0) { + call.serializeToStream(stream); + } + if ((flags & 16777216) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 33554432) != 0) { + stream.writeInt32(0x1cb5c415); + count = pending_suggestions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(pending_suggestions.get(a)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as.serializeToStream(stream); + } + if ((flags & 134217728) != 0) { + stream.writeString(theme_emoticon); + } + if ((flags & 268435456) != 0) { + stream.writeInt32(requests_pending); + } + if ((flags & 268435456) != 0) { + stream.writeInt32(0x1cb5c415); + count = recent_requesters.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_requesters.get(a)); + } + } + if ((flags & 536870912) != 0) { + default_send_as.serializeToStream(stream); + } + if ((flags & 1073741824) != 0) { + available_reactions.serializeToStream(stream); + } + if ((flags2 & 8192) != 0) { + stream.writeInt32(reactions_limit); + } + if ((flags2 & 16) != 0) { + stories.serializeToStream(stream); + } + if ((flags2 & 128) != 0) { + wallpaper.serializeToStream(stream); + } + if ((flags2 & 256) != 0) { + stream.writeInt32(boosts_applied); + } + if ((flags2 & 512) != 0) { + stream.writeInt32(boosts_unrestrict); + } + if ((flags2 & 1024) != 0) { + emojiset.serializeToStream(stream); + } + } + } + + + public static class TL_channelFull_layer177 extends TL_channelFull { public static final int constructor = 0x44c054a7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19566,6 +20057,7 @@ public class TLRPC { public boolean allow_app_hash; public boolean allow_missed_call; public boolean allow_firebase; + public boolean unknown_number; public ArrayList logout_tokens = new ArrayList<>(); public String token; public boolean app_sandbox; @@ -19590,6 +20082,7 @@ public class TLRPC { allow_app_hash = (flags & 16) != 0; allow_missed_call = (flags & 32) != 0; allow_firebase = (flags & 128) != 0; + unknown_number = (flags & 512) != 0; if ((flags & 64) != 0) { int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -19621,6 +20114,7 @@ public class TLRPC { flags = allow_missed_call ? (flags | 32) : (flags &~ 32); flags = allow_firebase ? (flags | 128) : (flags &~ 128); flags = app_sandbox ? (flags | 256) : (flags &~ 256); + flags = unknown_number ? (flags | 512) : (flags &~ 512); stream.writeInt32(flags); if ((flags & 64) != 0) { stream.writeInt32(0x1cb5c415); @@ -31010,6 +31504,7 @@ public class TLRPC { public ArrayList attributes = new ArrayList<>(); public String file_name_fixed; //custom public String localPath; //custom + public String localThumbPath; public static Document TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Document result = null; @@ -35039,6 +35534,12 @@ public class TLRPC { case TL_updateDeleteQuickReplyMessages.constructor: result = new TL_updateDeleteQuickReplyMessages(); break; + case TL_updateNewStoryReaction.constructor: + result = new TL_updateNewStoryReaction(); + break; + case TL_updateBroadcastRevenueTransactions.constructor: + result = new TL_updateBroadcastRevenueTransactions(); + break; } if (result == null && ApplicationLoader.applicationLoaderInstance != null) { result = ApplicationLoader.applicationLoaderInstance.parseTLUpdate(constructor); @@ -40620,21 +41121,24 @@ public class TLRPC { public boolean public_voters; public boolean multiple_choice; public boolean quiz; - public String question; - public ArrayList answers = new ArrayList<>(); + public TL_textWithEntities question = new TL_textWithEntities(); + public ArrayList answers = new ArrayList<>(); public int close_period; public int close_date; public static Poll TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Poll result = null; switch (constructor) { - case 0x86e18161: + case TL_poll.constructor: result = new TL_poll(); break; - case 0xaf746786: + case TL_poll_layer178.constructor: + result = new TL_poll_layer178(); + break; + case TL_poll_toDelete.constructor: result = new TL_poll_toDelete(); break; - case 0xd5529d06: + case TL_poll_layer111.constructor: result = new TL_poll_layer111(); break; } @@ -40647,10 +41151,9 @@ public class TLRPC { return result; } } - + public static class TL_poll extends Poll { - public static final int constructor = 0x86e18161; - + public static final int constructor = 0x58747131; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); @@ -40659,7 +41162,7 @@ public class TLRPC { public_voters = (flags & 2) != 0; multiple_choice = (flags & 4) != 0; quiz = (flags & 8) != 0; - question = stream.readString(exception); + question = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -40669,7 +41172,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_pollAnswer object = TL_pollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -40691,7 +41194,67 @@ public class TLRPC { flags = multiple_choice ? (flags | 4) : (flags &~ 4); flags = quiz ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); - stream.writeString(question); + question.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = answers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + answers.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(close_period); + } + if ((flags & 32) != 0) { + stream.writeInt32(close_date); + } + } + } + + public static class TL_poll_layer178 extends TL_poll { + public static final int constructor = 0x86e18161; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + flags = stream.readInt32(exception); + closed = (flags & 1) != 0; + public_voters = (flags & 2) != 0; + multiple_choice = (flags & 4) != 0; + quiz = (flags & 8) != 0; + question = new TL_textWithEntities(); + question.text = stream.readString(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++) { + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + answers.add(object); + } + if ((flags & 16) != 0) { + close_period = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + close_date = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + flags = closed ? (flags | 1) : (flags &~ 1); + flags = public_voters ? (flags | 2) : (flags &~ 2); + flags = multiple_choice ? (flags | 4) : (flags &~ 4); + flags = quiz ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeString(question == null ? "" : question.text); stream.writeInt32(0x1cb5c415); int count = answers.size(); stream.writeInt32(count); @@ -40718,7 +41281,8 @@ public class TLRPC { public_voters = (flags & 2) != 0; multiple_choice = (flags & 4) != 0; quiz = (flags & 8) != 0; - question = stream.readString(exception); + question = new TL_textWithEntities(); + question.text = stream.readString(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -40728,7 +41292,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_pollAnswer object = TL_pollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -40747,7 +41311,7 @@ public class TLRPC { flags = multiple_choice ? (flags | 4) : (flags &~ 4); flags = quiz ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); - stream.writeString(question); + stream.writeString(question == null ? "" : question.text); stream.writeInt32(0x1cb5c415); int count = answers.size(); stream.writeInt32(count); @@ -40771,7 +41335,8 @@ public class TLRPC { public_voters = (flags & 2) != 0; multiple_choice = (flags & 4) != 0; quiz = (flags & 8) != 0; - question = stream.readString(exception); + question = new TL_textWithEntities(); + question.text = stream.readString(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -40781,7 +41346,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_pollAnswer object = TL_pollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -40797,7 +41362,7 @@ public class TLRPC { flags = multiple_choice ? (flags | 4) : (flags &~ 4); flags = quiz ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); - stream.writeString(question); + stream.writeString(question == null ? "" : question.text); stream.writeInt32(0x1cb5c415); int count = answers.size(); stream.writeInt32(count); @@ -41852,67 +42417,22 @@ public class TLRPC { } } - public static class TL_sponsoredWebPage extends TLObject { - public static final int constructor = 0x3db8ec63; - - public int flags; - public String url; - public String site_name; - public Photo photo; - - public static TL_sponsoredWebPage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_sponsoredWebPage.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_sponsoredWebPage", constructor)); - } else { - return null; - } - } - TL_sponsoredWebPage result = new TL_sponsoredWebPage(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - url = stream.readString(exception); - site_name = stream.readString(exception); - if ((flags & 1) != 0) { - photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeString(url); - stream.writeString(site_name); - if ((flags & 1) != 0) { - photo.serializeToStream(stream); - } - } - } - public static class TL_sponsoredMessage extends TLObject { - public static final int constructor = 0xed5383f7; + public static final int constructor = 0xbdedf566; public int flags; public boolean recommended; - public boolean show_peer_photo; public boolean can_report; public byte[] random_id; - public Peer from_id; - public ChatInvite chat_invite; - public String chat_invite_hash; - public int channel_post; - public String start_param; - public BotApp app; - public TL_sponsoredWebPage webpage; + public String url; + public String title; public String message; + public Photo photo; public ArrayList entities = new ArrayList<>(); public String button_text; public String sponsor_info; public String additional_info; + public TL_peerColor color; public static TL_sponsoredMessage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_sponsoredMessage.constructor != constructor) { @@ -41930,30 +42450,10 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); recommended = (flags & 32) != 0; - show_peer_photo = (flags & 64) != 0; can_report = (flags & 4096) != 0; random_id = stream.readByteArray(exception); - if ((flags & 8) != 0) { - from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 16) != 0) { - chat_invite = ChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 16) != 0) { - chat_invite_hash = stream.readString(exception); - } - if ((flags & 4) != 0) { - channel_post = stream.readInt32(exception); - } - if ((flags & 1) != 0) { - start_param = stream.readString(exception); - } - if ((flags & 512) != 0) { - webpage = TL_sponsoredWebPage.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 1024) != 0) { - app = BotApp.TLdeserialize(stream, stream.readInt32(exception), exception); - } + url = stream.readString(exception); + title = stream.readString(exception); message = stream.readString(exception); if ((flags & 2) != 0) { int magic = stream.readInt32(exception); @@ -41972,9 +42472,13 @@ public class TLRPC { entities.add(object); } } - if ((flags & 2048) != 0) { - button_text = stream.readString(exception); + if ((flags & 64) != 0) { + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 8192) != 0) { + color = TL_peerColor.TLdeserialize(stream, stream.readInt32(exception), exception); + } + button_text = stream.readString(exception); if ((flags & 128) != 0) { sponsor_info = stream.readString(exception); } @@ -41986,31 +42490,11 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = recommended ? (flags | 32) : (flags &~ 32); - flags = show_peer_photo ? (flags | 64) : (flags &~ 64); flags = can_report ? (flags | 4096) : (flags &~ 4096); stream.writeInt32(flags); stream.writeByteArray(random_id); - if ((flags & 8) != 0) { - from_id.serializeToStream(stream); - } - if ((flags & 16) != 0) { - chat_invite.serializeToStream(stream); - } - if ((flags & 16) != 0) { - stream.writeString(chat_invite_hash); - } - if ((flags & 4) != 0) { - stream.writeInt32(channel_post); - } - if ((flags & 1) != 0) { - stream.writeString(start_param); - } - if ((flags & 512) != 0) { - webpage.serializeToStream(stream); - } - if ((flags & 1024) != 0) { - app.serializeToStream(stream); - } + stream.writeString(url); + stream.writeString(title); stream.writeString(message); if ((flags & 2) != 0) { stream.writeInt32(0x1cb5c415); @@ -42020,9 +42504,13 @@ public class TLRPC { entities.get(a).serializeToStream(stream); } } - if ((flags & 2048) != 0) { - stream.writeString(button_text); + if ((flags & 64) != 0) { + photo.serializeToStream(stream); } + if ((flags & 8192) != 0) { + color.serializeToStream(stream); + } + stream.writeString(button_text); if ((flags & 128) != 0) { stream.writeString(sponsor_info); } @@ -44994,7 +45482,7 @@ public class TLRPC { public static final int constructor = 0x881fb94b; public int hash; - public ArrayList groups = new ArrayList<>(); + public ArrayList groups = new ArrayList<>(); public void readParams(AbstractSerializedData stream, boolean exception) { hash = stream.readInt32(exception); @@ -45007,7 +45495,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_emojiGroup object = TL_emojiGroup.TLdeserialize(stream, stream.readInt32(exception), exception); + EmojiGroup object = EmojiGroup.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -45027,25 +45515,37 @@ public class TLRPC { } } - public static class TL_emojiGroup extends TLObject { - public static final int constructor = 0x7a9abda9; + public static class EmojiGroup extends TLObject { public String title; public long icon_emoji_id; public ArrayList emoticons = new ArrayList<>(); - public static TL_emojiGroup TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_emojiGroup.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_emojiGroup", constructor)); - } else { - return null; - } + public static EmojiGroup TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + EmojiGroup result = null; + switch (constructor) { + case TL_emojiGroup.constructor: + result = new TL_emojiGroup(); + break; + case TL_emojiGroupGreeting.constructor: + result = new TL_emojiGroupGreeting(); + break; + case TL_emojiGroupPremium.constructor: + result = new TL_emojiGroupPremium(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in EmojiGroup", constructor)); + } + if (result != null) { + result.readParams(stream, exception); } - TL_emojiGroup result = new TL_emojiGroup(); - result.readParams(stream, exception); return result; } + } + + public static class TL_emojiGroup extends EmojiGroup { + public static final int constructor = 0x7a9abda9; public void readParams(AbstractSerializedData stream, boolean exception) { title = stream.readString(exception); @@ -45076,6 +45576,53 @@ public class TLRPC { } } + public static class TL_emojiGroupGreeting extends EmojiGroup { + public static final int constructor = 0x80d26cc7; + + public void readParams(AbstractSerializedData stream, boolean exception) { + title = stream.readString(exception); + icon_emoji_id = stream.readInt64(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++) { + emoticons.add(stream.readString(exception)); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(title); + stream.writeInt64(icon_emoji_id); + stream.writeInt32(0x1cb5c415); + int count = emoticons.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(emoticons.get(a)); + } + } + } + + public static class TL_emojiGroupPremium extends EmojiGroup { + public static final int constructor = 0x93bcf34; + + public void readParams(AbstractSerializedData stream, boolean exception) { + title = stream.readString(exception); + icon_emoji_id = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(title); + stream.writeInt64(icon_emoji_id); + } + } + public static class TL_emojiKeyword extends EmojiKeyword { public static final int constructor = 0xd5b3b9f9; @@ -52204,6 +52751,7 @@ public class TLRPC { public boolean wallpaper_overridden; public boolean contact_require_premium; public boolean read_dates_private; + public boolean sponsored_enabled; public User user; public String about; public TL_contacts_link_layer101 link; @@ -52318,6 +52866,7 @@ public class TLRPC { contact_require_premium = (flags & 536870912) != 0; read_dates_private = (flags & 1073741824) != 0; flags2 = stream.readInt32(exception); + sponsored_enabled = (flags2 & 128) != 0; id = stream.readInt64(exception); if ((flags & 2) != 0) { about = stream.readString(exception); @@ -52421,6 +52970,7 @@ public class TLRPC { flags = contact_require_premium ? (flags | 536870912) : (flags &~ 536870912); flags = read_dates_private ? (flags | 1073741824) : (flags &~ 1073741824); stream.writeInt32(flags); + flags2 = sponsored_enabled ? (flags2 | 128) : (flags2 &~ 128); stream.writeInt32(flags2); stream.writeInt64(id); if ((flags & 2) != 0) { @@ -57118,6 +57668,21 @@ public class TLRPC { } } + public static class TL_messages_getEmojiStickerGroups extends TLObject { + public static final int constructor = 0x1dd840f5; + + public int hash; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return messages_EmojiGroups.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(hash); + } + } + public static class TL_messages_getEmojiProfilePhotoGroups extends TLObject { public static final int constructor = 0x21a548f3; @@ -58605,6 +59170,7 @@ public class TLRPC { public static final int constructor = 0x4bc6589a; public int flags; + public boolean broadcasts_only; public int folder_id; public String q; public MessagesFilter filter; @@ -58621,6 +59187,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = broadcasts_only ? (flags | 2) : (flags &~ 2); stream.writeInt32(flags); if ((flags & 1) != 0) { stream.writeInt32(folder_id); @@ -62569,10 +63136,12 @@ public class TLRPC { } public static class TL_messages_setChatAvailableReactions extends TLObject { - public static final int constructor = 0xfeb16771; + public static final int constructor = 0x5a150bd4; + public int flags; public InputPeer peer; public ChatReactions available_reactions; + public int reactions_limit; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Updates.TLdeserialize(stream, constructor, exception); @@ -62580,8 +63149,12 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); peer.serializeToStream(stream); available_reactions.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(reactions_limit); + } } } @@ -65835,7 +66408,7 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { type = stream.readString(exception); bytes = stream.readByteArray(exception); - w = h = 50; + w = h = 512; svgPath = SvgHelper.doPath(SvgHelper.decompress(bytes)); } @@ -75081,6 +75654,42 @@ public class TLRPC { } } } + + public static class TL_updateNewStoryReaction extends Update { + public static final int constructor = 0x1824e40b; + + public int story_id; + public Peer peer; + public Reaction reaction; + + public void readParams(AbstractSerializedData stream, boolean exception) { + story_id = stream.readInt32(exception); + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + reaction = Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(story_id); + peer.serializeToStream(stream); + reaction.serializeToStream(stream); + } + } + + public static class TL_updateBroadcastRevenueTransactions extends Update { + public static final int constructor = 0x5c65d358; + + public TL_broadcastRevenueBalances balances; + + public void readParams(AbstractSerializedData stream, boolean exception) { + balances = TL_broadcastRevenueBalances.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + balances.serializeToStream(stream); + } + } public static class TL_updateSavedDialogPinned extends Update { public static final int constructor = 0xaeaf9e74; @@ -76440,8 +77049,9 @@ public class TLRPC { } public static class TL_channels_getChannelRecommendations extends TLObject { - public static int constructor = 0x83b70d97; + public static int constructor = 0x25a71742; + public int flags; public InputChannel channel; @Override @@ -76451,7 +77061,10 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - channel.serializeToStream(stream); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + channel.serializeToStream(stream); + } } } @@ -79491,4 +80104,190 @@ public class TLRPC { stream.writeString(slug); } } + + public static class TL_account_toggleSponsoredMessages extends TLObject { + public static final int constructor = 0xb9d9a38d; + + public boolean enabled; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeBool(enabled); + } + } + + public static class ReactionNotificationsFrom extends TLObject { + public static ReactionNotificationsFrom TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + ReactionNotificationsFrom result = null; + switch (constructor) { + case TL_reactionNotificationsFromContacts.constructor: + result = new TL_reactionNotificationsFromContacts(); + break; + case TL_reactionNotificationsFromAll.constructor: + result = new TL_reactionNotificationsFromAll(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in ReactionNotificationsFrom", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_reactionNotificationsFromContacts extends ReactionNotificationsFrom { + public static final int constructor = 0xbac3a61a; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_reactionNotificationsFromAll extends ReactionNotificationsFrom { + public static final int constructor = 0x4b9e22a0; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_reactionsNotifySettings extends TLObject { + public static final int constructor = 0x56e34970; + + public int flags; + public ReactionNotificationsFrom messages_notify_from; + public ReactionNotificationsFrom stories_notify_from; + public NotificationSound sound; + public boolean show_previews; + + public static TL_reactionsNotifySettings TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_reactionsNotifySettings.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_reactionsNotifySettings", constructor)); + } else { + return null; + } + } + TL_reactionsNotifySettings result = new TL_reactionsNotifySettings(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + messages_notify_from = ReactionNotificationsFrom.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2) != 0) { + stories_notify_from = ReactionNotificationsFrom.TLdeserialize(stream, stream.readInt32(exception), exception); + } + sound = NotificationSound.TLdeserialize(stream, stream.readInt32(exception), exception); + show_previews = stream.readBool(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + messages_notify_from.serializeToStream(stream); + } + if ((flags & 2) != 0) { + stories_notify_from.serializeToStream(stream); + } + sound.serializeToStream(stream); + stream.writeBool(show_previews); + } + } + + public static class TL_account_getReactionsNotifySettings extends TLObject { + public static final int constructor = 0x6dd654c; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_reactionsNotifySettings.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_account_setReactionsNotifySettings extends TLObject { + public static final int constructor = 0x316ce548; + + public TL_reactionsNotifySettings settings; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_reactionsNotifySettings.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + settings.serializeToStream(stream); + } + } + + public static class TL_auth_reportMissingCode extends TLObject { + public static final int constructor = 0xcb9deff6; + + public String phone_number; + public String phone_code_hash; + public String mnc; +// public String mcc; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(phone_number); + stream.writeString(phone_code_hash); + stream.writeString(mnc); +// stream.writeString(mcc); + } + } + + public static class TL_broadcastRevenueBalances extends TLObject { + public static final int constructor = 0x8438f1c6; + + public long current_balance; + public long available_balance; + public long overall_revenue; + + public static TL_broadcastRevenueBalances TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_broadcastRevenueBalances.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_broadcastRevenueBalances", constructor)); + } else { + return null; + } + } + TL_broadcastRevenueBalances result = new TL_broadcastRevenueBalances(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + current_balance = stream.readInt64(exception); + available_balance = stream.readInt64(exception); + overall_revenue = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(current_balance); + stream.writeInt64(available_balance); + stream.writeInt64(overall_revenue); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java index 2b34ec8fa..88bd2fecb 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java @@ -780,13 +780,11 @@ public class TL_stats { } public static class TL_broadcastRevenueStats extends TLObject { - public static final int constructor = 0xd07b4bad; + public static final int constructor = 0x5407e297; public StatsGraph top_hours_graph; public StatsGraph revenue_graph; - public long current_balance; - public long available_balance; - public long overall_revenue; + public TLRPC.TL_broadcastRevenueBalances balances; public double usd_rate; public static TL_broadcastRevenueStats TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -807,9 +805,7 @@ public class TL_stats { public void readParams(AbstractSerializedData stream, boolean exception) { top_hours_graph = StatsGraph.TLdeserialize(stream, stream.readInt32(exception), exception); revenue_graph = StatsGraph.TLdeserialize(stream, stream.readInt32(exception), exception); - current_balance = stream.readInt64(exception); - available_balance = stream.readInt64(exception); - overall_revenue = stream.readInt64(exception); + balances = TLRPC.TL_broadcastRevenueBalances.TLdeserialize(stream, stream.readInt32(exception), exception); usd_rate = stream.readDouble(exception); } @@ -818,9 +814,7 @@ public class TL_stats { stream.writeInt32(constructor); top_hours_graph.serializeToStream(stream); revenue_graph.serializeToStream(stream); - stream.writeInt64(current_balance); - stream.writeInt64(available_balance); - stream.writeInt64(overall_revenue); + balances.serializeToStream(stream); stream.writeDouble(usd_rate); } } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java index 3fce977ca..373cdc5da 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java @@ -736,10 +736,12 @@ public class TL_stories { } public static class TL_stories_stories extends TLObject { - public static final int constructor = 0x5dd8c3c8; + public static final int constructor = 0x63c3dd0a; + public int flags; public int count; public ArrayList stories = new ArrayList<>(); + public ArrayList pinned_to_top = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -757,6 +759,7 @@ public class TL_stories { } public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); count = stream.readInt32(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -773,6 +776,19 @@ public class TL_stories { } stories.add(object); } + if ((flags & 1) != 0) { + 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++) { + pinned_to_top.add(stream.readInt32(exception)); + } + } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -807,6 +823,7 @@ public class TL_stories { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); stream.writeInt32(count); stream.writeInt32(0x1cb5c415); int count = stories.size(); @@ -814,6 +831,14 @@ public class TL_stories { for (int a = 0; a < count; a++) { stories.get(a).serializeToStream(stream); } + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + count = pinned_to_top.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(pinned_to_top.get(a)); + } + } stream.writeInt32(0x1cb5c415); count = chats.size(); stream.writeInt32(count); @@ -3345,4 +3370,26 @@ public class TL_stories { stream.writeInt32(limit); } } + + public static class TL_togglePinnedToTop extends TLObject { + public static final int constructor = 0xb297e9b; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + } + } } 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 b45d2fde9..2a4f22557 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -54,6 +54,7 @@ import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.Utilities; import org.telegram.ui.Components.BackButtonMenu; import org.telegram.ui.bots.BotWebViewSheet; import org.telegram.ui.Components.Bulletin; @@ -1622,6 +1623,10 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F } onFragmentStackChanged("addFragmentToStack " + position); } else { + if (position == INavigationLayout.FORCE_ATTACH_VIEW_AS_FIRST) { + position = 0; + attachViewTo(fragment, position); + } fragmentsStack.add(position, fragment); onFragmentStackChanged("addFragmentToStack"); } @@ -1663,6 +1668,35 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F fragment.attachStoryViewer(containerView); } + private void attachViewTo(BaseFragment fragment, int position) { + View fragmentView = fragment.fragmentView; + if (fragmentView == null) { + fragmentView = fragment.createView(parentActivity); + } else { + ViewGroup parent = (ViewGroup) fragmentView.getParent(); + if (parent != null) { + fragment.onRemoveFromParent(); + parent.removeView(fragmentView); + } + } + if (!fragment.hasOwnBackground && fragmentView.getBackground() == null) { + fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } + containerView.addView(fragmentView, Utilities.clamp(position, containerView.getChildCount(), 0), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + if (fragment.actionBar != null && fragment.actionBar.shouldAddToContainer()) { + if (removeActionBarExtraHeight) { + fragment.actionBar.setOccupyStatusBar(false); + } + ViewGroup parent = (ViewGroup) fragment.actionBar.getParent(); + if (parent != null) { + parent.removeView(fragment.actionBar); + } + containerView.addView(fragment.actionBar); + fragment.actionBar.setTitleOverlayText(titleOverlayText, titleOverlayTextId, overlayAction); + } + fragment.attachStoryViewer(containerView); + } + private void closeLastFragmentInternalRemoveOld(BaseFragment fragment) { fragment.finishing = true; fragment.onPause(); 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 ace306d3a..5a33a2e7c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -1928,6 +1928,9 @@ public class ActionBarMenuItem extends FrameLayout { showSubItem(id, false); } + public View getSubItem(int id) { + return popupLayout.findViewWithTag(id); + } public void showSubItem(int id, boolean animated) { Item lazyItem = findLazyItem(id); if (lazyItem != null) { 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 3e171181f..8877d7a21 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -73,7 +73,7 @@ public class BottomSheet extends Dialog { protected int currentAccount = UserConfig.selectedAccount; protected ViewGroup containerView; - protected ContainerView container; + public ContainerView container; protected boolean keyboardVisible; protected int keyboardHeight; private WindowInsets lastInsets; @@ -584,25 +584,29 @@ public class BottomSheet extends Dialog { if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { l += getLeftInset(); } - if (smoothKeyboardAnimationEnabled && startAnimationRunnable == null && keyboardChanged && !dismissed && containerView.getTop() != t) { + if (smoothKeyboardAnimationEnabled && startAnimationRunnable == null && keyboardChanged && !dismissed && containerView.getTop() != t || smoothContainerViewLayoutUntil > 0 && System.currentTimeMillis() < smoothContainerViewLayoutUntil) { containerView.setTranslationY(containerView.getTop() - t); + onSmoothContainerViewLayout(containerView.getTranslationY()); if (keyboardContentAnimator != null) { keyboardContentAnimator.cancel(); } keyboardContentAnimator = ValueAnimator.ofFloat(containerView.getTranslationY(), 0); keyboardContentAnimator.addUpdateListener(valueAnimator -> { containerView.setTranslationY((Float) valueAnimator.getAnimatedValue()); + onSmoothContainerViewLayout(containerView.getTranslationY()); invalidate(); }); keyboardContentAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { containerView.setTranslationY(0); + onSmoothContainerViewLayout(containerView.getTranslationY()); invalidate(); } }); keyboardContentAnimator.setDuration(AdjustPanLayoutHelper.keyboardDuration).setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); keyboardContentAnimator.start(); + smoothContainerViewLayoutUntil = -1; } containerView.layout(l, t, l + containerView.getMeasuredWidth(), t + containerView.getMeasuredHeight()); } @@ -2093,4 +2097,13 @@ public class BottomSheet extends Dialog { this.playingImagesLayerNum = playingImages; this.openedLayerNum = onShowing; } + + private long smoothContainerViewLayoutUntil = -1; + public void smoothContainerViewLayout() { + smoothContainerViewLayoutUntil = System.currentTimeMillis() + 80; + } + + protected void onSmoothContainerViewLayout(float ty) { + + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java index 8fe20bab7..402a018ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java @@ -23,6 +23,7 @@ public interface INavigationLayout { int REBUILD_FLAG_REBUILD_LAST = 1, REBUILD_FLAG_REBUILD_ONLY_LAST = 2; int FORCE_NOT_ATTACH_VIEW = -2; + int FORCE_ATTACH_VIEW_AS_FIRST = -3; boolean presentFragment(NavigationParams params); boolean checkTransitionAnimation(); 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 166006f22..bdac9b46a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -4125,8 +4125,10 @@ public class Theme { public static final int key_premiumGradientBackground4 = colorsCount++; public static final int key_premiumGradientBackgroundOverlay = colorsCount++; public static final int key_premiumStartSmallStarsColor = colorsCount++; - public static final int key_premiumStartGradient1 = colorsCount++; - public static final int key_premiumStartGradient2 = colorsCount++; + public static final int key_premiumStarGradient1 = colorsCount++; + public static final int key_premiumStarGradient2 = colorsCount++; + public static final int key_premiumCoinGradient1 = colorsCount++; + public static final int key_premiumCoinGradient2 = colorsCount++; public static final int key_premiumStartSmallStarsColor2 = colorsCount++; public static final int key_premiumGradientBottomSheet1 = colorsCount++; public static final int key_premiumGradientBottomSheet2 = colorsCount++; @@ -4503,8 +4505,8 @@ public class Theme { themeAccentExclusionKeys.add(key_premiumGradientBackground3); themeAccentExclusionKeys.add(key_premiumGradientBackground4); themeAccentExclusionKeys.add(key_premiumStartSmallStarsColor); - themeAccentExclusionKeys.add(key_premiumStartGradient1); - themeAccentExclusionKeys.add(key_premiumStartGradient2); + themeAccentExclusionKeys.add(key_premiumStarGradient1); + themeAccentExclusionKeys.add(key_premiumStarGradient2); themeAccentExclusionKeys.add(key_stories_circle1); themeAccentExclusionKeys.add(key_stories_circle2); themeAccentExclusionKeys.add(key_stories_circle_dialog1); @@ -8545,7 +8547,7 @@ public class Theme { chat_radialProgress2Paint.setStyle(Paint.Style.STROKE); chat_audioTimePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); chat_livePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - chat_livePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + chat_livePaint.setTypeface(Typeface.DEFAULT_BOLD); chat_audioTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); chat_audioTitlePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); chat_audioPerformerPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); @@ -8876,7 +8878,7 @@ public class Theme { chat_contextResult_titleTextPaint.setTextSize(dp(15)); chat_contextResult_descriptionTextPaint.setTextSize(dp(13)); chat_radialProgressPaint.setStrokeWidth(dp(3)); - chat_radialProgress2Paint.setStrokeWidth(dp(2)); + chat_radialProgress2Paint.setStrokeWidth(dp(2.33f)); chat_commentTextPaint.setTextSize(dp(14)); chat_commentTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java index 060f89891..f74f0ea03 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java @@ -3,7 +3,6 @@ package org.telegram.ui.ActionBar; import static org.telegram.ui.ActionBar.Theme.*; import android.graphics.Color; -import android.util.Log; import android.util.SparseArray; import androidx.core.graphics.ColorUtils; @@ -758,8 +757,10 @@ public class ThemeColors { defaultColors[key_premiumGradientBackground3] = 0xffDB5C9D; defaultColors[key_premiumGradientBackground4] = 0xffF38926; defaultColors[key_premiumGradientBackgroundOverlay] = Color.WHITE; - defaultColors[key_premiumStartGradient1] = 0xffFFFFFF; - defaultColors[key_premiumStartGradient2] = 0xffE3ECFA; + defaultColors[key_premiumStarGradient1] = 0xffFFFFFF; + defaultColors[key_premiumStarGradient2] = 0xffE3ECFA; + defaultColors[key_premiumCoinGradient1] = -15436801; + defaultColors[key_premiumCoinGradient2] = -4167942; defaultColors[key_premiumStartSmallStarsColor] = ColorUtils.setAlphaComponent(Color.WHITE, 90); defaultColors[key_premiumStartSmallStarsColor2] = ColorUtils.setAlphaComponent(Color.WHITE, 90); defaultColors[key_premiumGradientBottomSheet1] = 0xff5B9DE7; @@ -1505,8 +1506,10 @@ public class ThemeColors { colorKeysMap.put(key_premiumGradientBackground4, "premiumGradientBackground4"); colorKeysMap.put(key_premiumGradientBackgroundOverlay, "premiumGradientBackgroundOverlay"); colorKeysMap.put(key_premiumStartSmallStarsColor, "premiumStartSmallStarsColor"); - colorKeysMap.put(key_premiumStartGradient1, "premiumStarGradient1"); - colorKeysMap.put(key_premiumStartGradient2, "premiumStarGradient2"); + colorKeysMap.put(key_premiumStarGradient1, "premiumStarGradient1"); + colorKeysMap.put(key_premiumStarGradient2, "premiumStarGradient2"); + colorKeysMap.put(key_premiumCoinGradient1, "premiumCoinGradient1"); + colorKeysMap.put(key_premiumCoinGradient2, "premiumCoinGradient2"); colorKeysMap.put(key_premiumStartSmallStarsColor2, "premiumStartSmallStarsColor2"); colorKeysMap.put(key_premiumGradientBottomSheet1, "premiumGradientBottomSheet1"); colorKeysMap.put(key_premiumGradientBottomSheet2, "premiumGradientBottomSheet2"); 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 dea5bef42..94722c2c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -63,15 +63,15 @@ import java.util.concurrent.ConcurrentHashMap; public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { - private final int VIEW_TYPE_PROFILE_CELL = 0; - private final int VIEW_TYPE_GRAY_SECTION = 1; - private final int VIEW_TYPE_DIALOG_CELL = 2; - private final int VIEW_TYPE_TOPIC_CELL = 3; - private final int VIEW_TYPE_LOADING = 4; - private final int VIEW_TYPE_HASHTAG_CELL = 5; - private final int VIEW_TYPE_CATEGORY_LIST = 6; - private final int VIEW_TYPE_ADD_BY_PHONE = 7; - private final int VIEW_TYPE_INVITE_CONTACT_CELL = 8; + public final static int VIEW_TYPE_PROFILE_CELL = 0; + public final static int VIEW_TYPE_GRAY_SECTION = 1; + public final int VIEW_TYPE_DIALOG_CELL = 2; + public final int VIEW_TYPE_TOPIC_CELL = 3; + public final int VIEW_TYPE_LOADING = 4; + public final int VIEW_TYPE_HASHTAG_CELL = 5; + public final int VIEW_TYPE_CATEGORY_LIST = 6; + public final int VIEW_TYPE_ADD_BY_PHONE = 7; + public final int VIEW_TYPE_INVITE_CONTACT_CELL = 8; private Context mContext; private Runnable searchRunnable; private Runnable searchRunnable2; @@ -1336,6 +1336,12 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } i -= contactsCount + 1; } + if (localCount + localServerCount > 0 && (getRecentItemsCount() > 0 || !searchTopics.isEmpty())) { + if (i == 0) { + return false; + } + i--; + } if (i >= 0 && i < localCount) { return false; } @@ -1483,12 +1489,23 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { CharSequence username = null; CharSequence name = null; boolean isRecent = false; + boolean isGlobal = isGlobalSearch(position); String un = null; Object obj = getItem(position); if (obj instanceof TLRPC.User) { user = (TLRPC.User) obj; un = UserObject.getPublicUsername(user); + if (un != null && lastSearchText != null && !un.toLowerCase().contains(lastSearchText.toLowerCase())) { + if (user.usernames != null) { + for (int i = 0; i < user.usernames.size(); ++i) { + TLRPC.TL_username u = user.usernames.get(i); + if (u != null && u.active && u.username.toLowerCase().contains(lastSearchText.toLowerCase())) { + un = u.username; + } + } + } + } } else if (obj instanceof TLRPC.Chat) { chat = MessagesController.getInstance(currentAccount).getChat(((TLRPC.Chat) obj).id); if (chat == null) { @@ -1557,7 +1574,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); name = spannableStringBuilder; } - if (un != null && user == null) { + if (un != null && (user == null || isGlobal)) { if (foundUserName.startsWith("@")) { foundUserName = foundUserName.substring(1); } 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 8a0dc23a7..f11b3a597 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -311,6 +311,7 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter { } UserConfig me = UserConfig.getInstance(UserConfig.selectedAccount); boolean showDivider = false; + items.add(new Item(16, LocaleController.getString(R.string.MyProfile), R.drawable.left_status_profile)); if (me != null && me.isPremium()) { if (me.getEmojiStatus() != null) { items.add(new Item(15, LocaleController.getString("ChangeEmojiStatus", R.string.ChangeEmojiStatus), R.drawable.msg_status_edit)); @@ -319,10 +320,11 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter { } showDivider = true; } - if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) { - items.add(new Item(16, LocaleController.getString("ProfileMyStories", R.string.ProfileMyStories), R.drawable.msg_menu_stories)); - showDivider = true; - } +// if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) { +// items.add(new Item(17, LocaleController.getString(R.string.ProfileStories), R.drawable.msg_menu_stories)); +// showDivider = true; +// } + showDivider = true; if (ApplicationLoader.applicationLoaderInstance != null) { if (ApplicationLoader.applicationLoaderInstance.extendDrawer(items)) { showDivider = true; 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 daff53eba..f950cf40f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -321,8 +321,9 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca return 2; } else if (currentMessageObject != null) { return 2 + (currentLiveLocations.isEmpty() ? 1 : currentLiveLocations.size() + 3); - } else if (locationType == 2) { - return 2 + currentLiveLocations.size(); + } else if (locationType == LocationActivity.LOCATION_TYPE_LIVE) { + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + return 2 + currentLiveLocations.size() + (currentInfo != null && currentInfo.period != 0x7FFFFFFF ? 1 : 0); } else { if (searching || !searched || places.isEmpty()) { int count = 6; @@ -368,7 +369,7 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca emptyCell.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, overScrollHeight)); break; case VIEW_TYPE_SEND_LOCATION: - view = new SendLocationCell(mContext, false, resourcesProvider); + view = new SendLocationCell(mContext, false, false, resourcesProvider); break; case VIEW_TYPE_HEADER: view = new HeaderCell(mContext, resourcesProvider); @@ -384,7 +385,13 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca view = new LocationPoweredCell(mContext, resourcesProvider); break; case VIEW_TYPE_LIVE_LOCATION: { - SendLocationCell cell = new SendLocationCell(mContext, true, resourcesProvider); + SendLocationCell cell = new SendLocationCell(mContext, true, false, resourcesProvider); + cell.setDialogId(dialogId); + view = cell; + break; + } + case VIEW_TYPE_DELETE_LIVE_LOCATION: { + SendLocationCell cell = new SendLocationCell(mContext, true, true, resourcesProvider); cell.setDialogId(dialogId); view = cell; break; @@ -428,11 +435,12 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca public static final int VIEW_TYPE_LOADING = 4; public static final int VIEW_TYPE_FOOTER = 5; public static final int VIEW_TYPE_LIVE_LOCATION = 6; - public static final int VIEW_TYPE_SHARING = 7; - public static final int VIEW_TYPE_DIRECTION = 8; - public static final int VIEW_TYPE_SHADOW = 9; - public static final int VIEW_TYPE_EMPTY = 10; - public static final int VIEW_TYPE_STORY_LOCATION = 11; + public static final int VIEW_TYPE_DELETE_LIVE_LOCATION = 7; + public static final int VIEW_TYPE_SHARING = 8; + public static final int VIEW_TYPE_DIRECTION = 9; + public static final int VIEW_TYPE_SHADOW = 10; + public static final int VIEW_TYPE_EMPTY = 11; + public static final int VIEW_TYPE_STORY_LOCATION = 12; @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { @@ -493,6 +501,12 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca ((LocationLoadingCell) holder.itemView).setLoading(searching); break; case VIEW_TYPE_LIVE_LOCATION: + SendLocationCell cell2 = (SendLocationCell) holder.itemView; + cell2.setHasLocation(gpsLocation != null); + cell2.useDivider = position + 1 < getItemCount() && getItemViewType(position + 1) == VIEW_TYPE_DELETE_LIVE_LOCATION; + cell2.invalidate(); + break; + case VIEW_TYPE_DELETE_LIVE_LOCATION: ((SendLocationCell) holder.itemView).setHasLocation(gpsLocation != null); break; case VIEW_TYPE_SHARING: @@ -504,7 +518,14 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca } else if (currentMessageObject != null && position == 1) { locationCell.setDialog(currentMessageObject, gpsLocation, myLocationDenied); } else { - locationCell.setDialog(currentLiveLocations.get(position - (currentMessageObject != null ? 5 : 2)), gpsLocation); + int index = position - (currentMessageObject != null ? 5 : 2); + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + if (currentInfo != null && currentInfo.period != 0x7FFFFFFF) { + index--; + } + if (index < 0 || index >= currentLiveLocations.size()) + return; + locationCell.setDialog(currentLiveLocations.get(index), gpsLocation); } break; case VIEW_TYPE_EMPTY: @@ -549,9 +570,14 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca } else if (i > 4 && i < places.size() + 4) { return currentLiveLocations.get(i - 5); } - } else if (locationType == 2) { - if (i >= 2) { - return currentLiveLocations.get(i - 2); + } else if (locationType == LocationActivity.LOCATION_TYPE_LIVE) { + int start = 2; + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + if (currentInfo != null && currentInfo.period != 0x7FFFFFFF) { + start++; + } + if (i >= start) { + return currentLiveLocations.get(i - start); } return null; } else if (locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { @@ -592,6 +618,10 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca if (locationType == LocationActivity.LOCATION_TYPE_GROUP) { return VIEW_TYPE_SEND_LOCATION; } + LocationController.SharingLocationInfo currentInfo = null; + if (locationType == LocationActivity.LOCATION_TYPE_LIVE || locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { + currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + } if (currentMessageObject != null) { if (currentLiveLocations.isEmpty()) { if (position == 2) { @@ -609,8 +639,14 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca } return VIEW_TYPE_SHARING; } - if (locationType == 2) { + if (locationType == LocationActivity.LOCATION_TYPE_LIVE) { + if (position == 2 && currentInfo != null && currentInfo.period != 0x7FFFFFFF) { + return VIEW_TYPE_DELETE_LIVE_LOCATION; + } if (position == 1) { + if (currentInfo != null && currentInfo.period == 0x7FFFFFFF) { + return VIEW_TYPE_DELETE_LIVE_LOCATION; + } shareLiveLocationPotistion = position; return VIEW_TYPE_LIVE_LOCATION; } else { @@ -620,9 +656,14 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca if (locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { if (position == 1) { return VIEW_TYPE_SEND_LOCATION; - } else if (position == 2) { - shareLiveLocationPotistion = position; - return VIEW_TYPE_LIVE_LOCATION; + } else if (position == LocationActivity.LOCATION_TYPE_LIVE) { + if (currentInfo != null) { + shareLiveLocationPotistion = -1; + return VIEW_TYPE_DELETE_LIVE_LOCATION; + } else { + shareLiveLocationPotistion = position; + return VIEW_TYPE_LIVE_LOCATION; + } } else if (position == 3) { return VIEW_TYPE_SHADOW; } else if (position == 4) { @@ -642,7 +683,7 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca return VIEW_TYPE_STORY_LOCATION; } if (this.street != null) { - if (position == 2) { + if (position == LocationActivity.LOCATION_TYPE_LIVE) { return VIEW_TYPE_STORY_LOCATION; } position--; @@ -672,7 +713,7 @@ public class LocationActivityAdapter extends BaseLocationAdapter implements Loca if (viewType == VIEW_TYPE_LIVE_LOCATION) { return !(LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId) == null && gpsLocation == null); } - return viewType == VIEW_TYPE_SEND_LOCATION || viewType == VIEW_TYPE_LOCATION || viewType == VIEW_TYPE_SHARING || viewType == VIEW_TYPE_STORY_LOCATION; + return viewType == VIEW_TYPE_SEND_LOCATION || viewType == VIEW_TYPE_LOCATION || viewType == VIEW_TYPE_SHARING || viewType == VIEW_TYPE_STORY_LOCATION || viewType == VIEW_TYPE_DELETE_LIVE_LOCATION; } private int getThemedColor(int key) { 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 fab75be41..af2b0934f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -65,6 +65,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { private int searchPointer; private ArrayList allUnregistredContacts; private ArrayList unregistredContacts = new ArrayList<>(); + private String lastQuery; public SearchAdapter(Context context, LongSparseArray arg1, LongSparseArray selected, boolean usernameSearch, boolean mutual, boolean chats, boolean bots, boolean self, boolean phones, int searchChannelId) { @@ -133,6 +134,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { private void processSearch(final String query) { AndroidUtilities.runOnUIThread(() -> { + lastQuery = query; if (allowUsernameSearch) { searchAdapterHelper.queryServerSearch(query, true, allowChats, allowBots, allowSelf, false, channelId, allowPhoneNumbers, -1, 1); } @@ -260,8 +262,8 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { public int getItemCount() { unregistredContactsHeaderRow = -1; int count = searchResult.size(); - unregistredContactsHeaderRow = count; if (!unregistredContacts.isEmpty()) { + unregistredContactsHeaderRow = count; count += unregistredContacts.size() + 1; } @@ -359,7 +361,18 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { String un = null; boolean self = false; if (object instanceof TLRPC.User) { - un = ((TLRPC.User) object).username; + TLRPC.User user = (TLRPC.User) object; + un = UserObject.getPublicUsername((TLRPC.User) object); + if (un != null && lastQuery != null && !un.toLowerCase().contains(lastQuery.toLowerCase())) { + if (user.usernames != null) { + for (int i = 0; i < user.usernames.size(); ++i) { + TLRPC.TL_username u = user.usernames.get(i); + if (u != null && u.active && u.username.toLowerCase().contains(lastQuery.toLowerCase())) { + un = u.username; + } + } + } + } id = ((TLRPC.User) object).id; self = ((TLRPC.User) object).self; } else if (object instanceof TLRPC.Chat) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java index b2aa61e9e..88c4ad6db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java @@ -13,6 +13,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.MessagesController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AvatarDrawable; @@ -21,17 +22,20 @@ public class AvatarSpan extends ReplacementSpan { private final Paint shadowPaint; private final ImageReceiver imageReceiver; private final AvatarDrawable avatarDrawable; - private final int sz; + private float sz; private final int currentAccount; private View parent; - public AvatarSpan(View parent, int currentAccount, int sz) { + public AvatarSpan(View parent, int currentAccount) { + this(parent, currentAccount, 18); + } + + public AvatarSpan(View parent, int currentAccount, float sz) { this.currentAccount = currentAccount; this.imageReceiver = new ImageReceiver(parent); this.avatarDrawable = new AvatarDrawable(); - imageReceiver.setRoundRadius(dp(sz)); - this.sz = sz; + setSize(sz); this.shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); shadowPaint.setShadowLayer(dp(1), 0, dp(.66f), 0x33000000); @@ -39,6 +43,11 @@ public class AvatarSpan extends ReplacementSpan { setParent(parent); } + public void setSize(float sz) { + imageReceiver.setRoundRadius(dp(sz)); + this.sz = sz; + } + public void setParent(View parent) { if (this.parent == parent) return; if (this.parent != null) { @@ -88,6 +97,11 @@ public class AvatarSpan extends ReplacementSpan { imageReceiver.setForUserOrChat(user, avatarDrawable); } + public void setName(String name) { + avatarDrawable.setInfo(0, name, null, null, null, null); + imageReceiver.setForUserOrChat(null, avatarDrawable); + } + @Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) { return dp(sz); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java index cc6366e02..191d4dbc7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java @@ -9,16 +9,9 @@ import android.graphics.Matrix; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.text.Editable; -import android.text.InputFilter; -import android.text.InputType; -import android.text.Spanned; import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -29,10 +22,8 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; @@ -40,26 +31,21 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; -import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.EditTextCell; import org.telegram.ui.Cells.TextCell; -import org.telegram.ui.Components.AnimatedColor; import org.telegram.ui.Components.AnimatedFloat; -import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.ChatGreetingsView; import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.CrossfadeDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; -import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.SizeNotifierFrameLayout; -import org.telegram.ui.Components.Text; import org.telegram.ui.Components.UItem; import org.telegram.ui.Components.UniversalAdapter; import org.telegram.ui.Components.UniversalFragment; -import org.telegram.ui.Stories.StoryViewer; +import org.telegram.ui.ContentPreviewViewer; import org.telegram.ui.Stories.recorder.EmojiBottomSheet; import org.telegram.ui.Stories.recorder.KeyboardNotifier; import org.telegram.ui.Stories.recorder.PreviewView; @@ -113,6 +99,9 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica private boolean stickerRandom = true; private TLRPC.Document sticker = getMediaDataController().getGreetingsSticker(); + private String inputStickerPath; + private TLRPC.InputDocument inputSticker; + private boolean keyboardVisible; @Override @@ -303,8 +292,10 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica items.add(UItem.asCustom(messageEdit)); if (stickerRandom) { items.add(UItem.asButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), getString(R.string.BusinessIntroStickerRandom))); + } else if (inputStickerPath != null) { + items.add(UItem.asStickerButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), inputStickerPath)); } else { - items.add(UItem.asButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), sticker)); + items.add(UItem.asStickerButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), sticker)); } items.add(UItem.asShadow(getString(R.string.BusinessIntroInfo))); if (clearVisible = !isEmpty()) { @@ -319,13 +310,6 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica return TextUtils.isEmpty(titleEdit.getText()) && TextUtils.isEmpty(messageEdit.getText()) && stickerRandom; } - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.userInfoDidLoad) { - setValue(); - } - } - private String currentTitle, currentMessage; private long currentSticker; @@ -347,6 +331,7 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica } else { titleEdit.setText(currentTitle = ""); messageEdit.setText(currentMessage = ""); + inputSticker = null; sticker = null; } currentSticker = sticker == null ? 0 : sticker.id; @@ -371,14 +356,16 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica @Override protected void onClick(UItem item, View view, int position, float x, float y) { if (item.id == BUTTON_STICKER) { - EmojiBottomSheet sheet = new EmojiBottomSheet(getContext(), true, getResourceProvider()); + EmojiBottomSheet sheet = new EmojiBottomSheet(getContext(), true, getResourceProvider(), true); sheet.whenDocumentSelected((parentObject, document, a) -> { stickerRandom = false; AndroidUtilities.cancelRunOnUIThread(updateRandomStickerRunnable); greetingsView.setSticker(sticker = document); ((TextCell) view).setValueSticker(document); checkDone(true, false); + return true; }); + sheet.whenPlusSelected(this::openCustomStickerEditor); showDialog(sheet); } else if (item.id == BUTTON_REMOVE) { titleEdit.setText(""); @@ -405,7 +392,7 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica return ( !TextUtils.equals(titleEdit.getText().toString(), currentTitle == null ? "" : currentTitle) || !TextUtils.equals(messageEdit.getText().toString(), currentMessage == null ? "" : currentMessage) || - (stickerRandom || sticker == null ? 0 : sticker.id) != currentSticker + (stickerRandom || sticker == null ? 0 : sticker.id) != currentSticker || (!stickerRandom && inputSticker != null) ); } @@ -452,9 +439,13 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica req.intro = new TLRPC.TL_inputBusinessIntro(); req.intro.title = titleEdit.getText().toString(); req.intro.description = messageEdit.getText().toString(); - if (!stickerRandom && sticker != null) { + if (!stickerRandom && (sticker != null || inputSticker != null)) { req.intro.flags |= 1; - req.intro.sticker = getMessagesController().getInputDocument(sticker); + if (inputSticker != null) { + req.intro.sticker = inputSticker; + } else { + req.intro.sticker = getMessagesController().getInputDocument(sticker); + } } if (userFull != null) { @@ -482,6 +473,9 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica doneButtonDrawable.animateToProgress(0f); BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); } else { + if (inputSticker != null) { + getMessagesController().loadFullUser(getUserConfig().getCurrentUser(), 0, true); + } finishFragment(); } })); @@ -503,4 +497,83 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica } + private void openCustomStickerEditor() { + ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(null); + if (getParentActivity() == null) { + return; + } + createChatAttachView(); + chatAttachAlert.getPhotoLayout().loadGalleryPhotos(); + chatAttachAlert.setMaxSelectedPhotos(1, false); + chatAttachAlert.setOpenWithFrontFaceCamera(true); + chatAttachAlert.enableStickerMode(this::setCustomSticker); + chatAttachAlert.init(); + chatAttachAlert.parentThemeDelegate = null; + if (visibleDialog != null) { + chatAttachAlert.show(); + } else { + showDialog(chatAttachAlert); + } + } + + private ChatAttachAlert chatAttachAlert; + private void createChatAttachView() { + if (getParentActivity() == null || getContext() == null) { + return; + } + if (chatAttachAlert == null) { + chatAttachAlert = new ChatAttachAlert(getParentActivity(), this, false, false, true, resourceProvider) { + @Override + public void dismissInternal() { + if (chatAttachAlert != null && chatAttachAlert.isShowing()) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + super.dismissInternal(); + } + + @Override + public void onDismissAnimationStart() { + if (chatAttachAlert != null) { + chatAttachAlert.setFocusable(false); + } + if (chatAttachAlert != null && chatAttachAlert.isShowing()) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + } + }; + chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() { + @Override + public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate, boolean forceDocument) { + + } + @Override + public void doOnIdle(Runnable runnable) { + NotificationCenter.getInstance(currentAccount).doOnIdle(runnable); + } + }); + } + } + + private void setCustomSticker(String localPath, TLRPC.InputDocument inputDocument) { + chatAttachAlert.dismiss(); + + inputStickerPath = localPath; + inputSticker = inputDocument; + + stickerRandom = false; + AndroidUtilities.cancelRunOnUIThread(updateRandomStickerRunnable); + greetingsView.setSticker(inputStickerPath); + checkDone(true, false); + if (listView != null && listView.adapter != null) { + listView.adapter.update(true); + } + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.userInfoDidLoad) { + setValue(); + } + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java index c7a0792a0..b7bb7881d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java @@ -370,7 +370,7 @@ public class ChatbotsActivity extends BaseFragment { } } - private void clear() { + private void clear(View view) { selectedBot = null; listView.adapter.update(true); checkDone(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java index cb5bb00af..f1c722f4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java @@ -1,6 +1,7 @@ package org.telegram.ui.Business; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.formatString; import static org.telegram.messenger.LocaleController.getString; import android.content.Context; @@ -20,6 +21,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.TLObject; @@ -298,8 +300,15 @@ public class OpeningHoursActivity extends BaseFragment implements NotificationCe if (!days[prevDay].isEmpty() && days[prevDay].get(days[prevDay].size() - 1).end >= 24 * 60) { days[prevDay].get(days[prevDay].size() - 1).end = 24 * 60 - 1; } + + int periodEnd = Math.min(m - start - 1, 24 * 60 * 2 - 1); + ArrayList nextDay = days[(7 + i + 1) % 7]; + if (periodEnd >= 24 * 60 && !nextDay.isEmpty() && nextDay.get(0).start < periodEnd - 24 * 60) { + periodEnd = 24 * 60 + nextDay.get(0).start - 1; + } + days[i].clear(); - days[i].add(new Period(0, 24 * 60 - 1)); + days[i].add(new Period(0, periodEnd)); } else { int nextDay = (i + 1) % 7; if (!days[i].isEmpty() && !days[nextDay].isEmpty()) { @@ -333,6 +342,44 @@ public class OpeningHoursActivity extends BaseFragment implements NotificationCe return hours; } + public static String toString(int currentAccount, TLRPC.User user, TLRPC.TL_businessWorkHours business_work_hours) { + if (business_work_hours == null) return null; + ArrayList[] days = OpeningHoursActivity.getDaysHours(business_work_hours.weekly_open); + StringBuilder sb = new StringBuilder(); + if (user != null) { + sb.append(formatString(R.string.BusinessHoursCopyHeader, UserObject.getUserName(user))).append("\n"); + } + for (int i = 0; i < days.length; ++i) { + ArrayList periods = days[i]; + String day = DayOfWeek.values()[i].getDisplayName(TextStyle.FULL, LocaleController.getInstance().getCurrentLocale()); + day = day.substring(0, 1).toUpperCase() + day.substring(1); + sb.append(day).append(": "); + if (OpeningHoursActivity.isFull(periods)) { + sb.append(LocaleController.getString(R.string.BusinessHoursProfileOpen)); + } else if (periods.isEmpty()) { + sb.append(LocaleController.getString(R.string.BusinessHoursProfileClose)); + } else { + for (int j = 0; j < periods.size(); ++j) { + if (j > 0) sb.append(", "); + OpeningHoursActivity.Period p = periods.get(j); + sb.append(OpeningHoursActivity.Period.timeToString(p.start)); + sb.append(" - "); + sb.append(OpeningHoursActivity.Period.timeToString(p.end)); + } + } + sb.append("\n"); + } + TLRPC.TL_timezone timezone = TimezonesController.getInstance(currentAccount).findTimezone(business_work_hours.timezone_id); + Calendar calendar = Calendar.getInstance(); + int currentUtcOffset = calendar.getTimeZone().getRawOffset() / 1000; + int valueUtcOffset = timezone == null ? 0 : timezone.utc_offset; + int utcOffset = (currentUtcOffset - valueUtcOffset) / 60; + if (utcOffset != 0 && timezone != null) { + sb.append(formatString(R.string.BusinessHoursCopyFooter, TimezonesController.getInstance(currentAccount).getTimezoneName(timezone, true))); + } + return sb.toString(); + } + private void processDone() { if (doneButtonDrawable.getProgress() > 0f) return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java index dfe41aafe..3885fe90d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java @@ -132,7 +132,7 @@ public class OpeningHoursDayActivity extends BaseFragment { if (periods.size() >= maxPeriodsCount) { return false; } - return periods.isEmpty() || is24() || periods.get(periods.size() - 1).end < max - 2; + return periods.isEmpty() || is24() || periods.get(periods.size() - 1).end < Math.min(24 * 60 - 2, max - 2); } private void onClick(UItem item, View view, int position, float x, float y) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java index 04038a42a..e95133cd2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java @@ -204,7 +204,7 @@ public class ProfileHoursCell extends LinearLayout { TLRPC.TL_timezone timezone = timezonesController.findTimezone(value.timezone_id); Calendar calendar = Calendar.getInstance(); - int currentUtcOffset = calendar.getTimeZone().getRawOffset() / 1000; + int currentUtcOffset = calendar.getTimeZone().getOffset(System.currentTimeMillis()) / 1000; int valueUtcOffset = timezone == null ? 0 : timezone.utc_offset; int utcOffset = (currentUtcOffset - valueUtcOffset) / 60; switchText.setVisibility(utcOffset != 0 && !is24x7 ? View.VISIBLE : View.GONE); @@ -287,15 +287,15 @@ public class ProfileHoursCell extends LinearLayout { TextView textView = k == 0 ? timeText[i][a] : labelTimeText[a]; if (i == 0 && !open_now && k == 1) { int opensPeriodTime = -1; - for (int j = 0; j < weekly_open.size(); ++j) { - TLRPC.TL_businessWeeklyOpen weekly = weekly_open.get(j); + for (int j = 0; j < adapted_weekly_open.size(); ++j) { + TLRPC.TL_businessWeeklyOpen weekly = adapted_weekly_open.get(j); if (nowPeriodTime < weekly.start_minute) { opensPeriodTime = weekly.start_minute; break; } } - if (opensPeriodTime == -1 && !weekly_open.isEmpty()) { - opensPeriodTime = weekly_open.get(0).start_minute; + if (opensPeriodTime == -1 && !adapted_weekly_open.isEmpty()) { + opensPeriodTime = adapted_weekly_open.get(0).start_minute; } if (opensPeriodTime == -1) { textView.setText(getString(R.string.BusinessHoursProfileClose)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index 72706854f..55929f886 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -148,7 +148,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe private LinearLayoutManager layoutManager; AlertDialog progressDialog; - private boolean[] selected = new boolean[] { true, true, true, true, true, true, true, true, true, true }; + private boolean[] selected = new boolean[] { true, true, true, true, true, true, true, true, true, true, true }; private long databaseSize = -1; private long cacheSize = -1, cacheEmojiSize = -1, cacheTempSize = -1; private long documentsSize = -1; @@ -157,6 +157,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe private long musicSize = -1; private long photoSize = -1; private long videoSize = -1; + private long logsSize = -1; private long stickersCacheSize = -1; private long totalSize = -1; private long totalDeviceSize = -1; @@ -247,7 +248,11 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe stickersCacheSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 3); long audioSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_AUDIO), 0); long storiesSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_STORIES), 0); - final long totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; + long logsSize = getDirectorySize(AndroidUtilities.getLogsDir(), 1); + if (!BuildVars.DEBUG_VERSION && logsSize < 1024 * 1024 * 256) { + logsSize = 0; + } + final long totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize + logsSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); if (!canceled) { AndroidUtilities.runOnUIThread(() -> { @@ -349,6 +354,13 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe if (canceled) { return; } + logsSize = getDirectorySize(AndroidUtilities.getLogsDir(), 1); + if (!BuildVars.DEBUG_VERSION && logsSize < 1024 * 1024 * 256) { + logsSize = 0; + } + if (canceled) { + return; + } documentsSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_DOCUMENT), 1); documentsSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES), 1); if (canceled) { @@ -373,7 +385,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe if (canceled) { return; } - totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + storiesSize + stickersCacheSize; + totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + logsSize + audioSize + photoSize + documentsSize + musicSize + storiesSize + stickersCacheSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); File path; @@ -440,13 +452,13 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe private void updateChart() { if (cacheChart != null) { if (!calculating && totalSize > 0) { - CacheChart.SegmentSize[] segments = new CacheChart.SegmentSize[10]; + CacheChart.SegmentSize[] segments = new CacheChart.SegmentSize[11]; for (int i = 0; i < itemInners.size(); ++i) { ItemInner item = itemInners.get(i); if (item.viewType == VIEW_TYPE_SECTION) { if (item.index < 0) { if (collapsed) { - segments[9] = CacheChart.SegmentSize.of(item.size, selected[9]); + segments[10] = CacheChart.SegmentSize.of(item.size, selected[10]); } } else { segments[item.index] = CacheChart.SegmentSize.of(item.size, selected[item.index]); @@ -732,19 +744,22 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe if (cacheTempSize > 0) { sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalMiscellaneousCache), 8, cacheTempSize, Theme.key_statisticChartLine_purple)); } + if (logsSize > 0) { + sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalLogsCache), 9, logsSize, Theme.key_statisticChartLine_golden)); + } if (!sections.isEmpty()) { Collections.sort(sections, (a, b) -> Long.compare(b.size, a.size)); sections.get(sections.size() - 1).last = true; hasCache = true; if (tempSizes == null) { - tempSizes = new float[10]; + tempSizes = new float[11]; } for (int i = 0; i < tempSizes.length; ++i) { tempSizes[i] = (float) size(i); } if (percents == null) { - percents = new int[10]; + percents = new int[11]; } AndroidUtilities.roundPercents(tempSizes, percents); @@ -758,7 +773,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe sum += sections.get(i).size; sumPercents += percents[sections.get(i).index]; } - percents[9] = sumPercents; + percents[10] = sumPercents; itemInners.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalOther), -1, sum, Theme.key_statisticChartLine_golden)); if (!collapsed) { itemInners.addAll(sections.subList(MAX_NOT_COLLAPSED, sections.size())); @@ -964,7 +979,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe long clearedSize = 0; boolean allItemsClear = true; final int[] clearDirI = new int[] { 0 }; - int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0) + (selected[8] ? 1 : 0); + int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0) + (selected[8] ? 1 : 0) + (selected[9] ? 1 : 0); long time = System.currentTimeMillis(); Utilities.Callback updateProgress = t -> { onProgress.run(clearDirI[0] / (float) clearDirCount + (1f / clearDirCount) * MathUtils.clamp(t, 0, 1), false); @@ -973,7 +988,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe final long now = System.currentTimeMillis(); onProgress.run(clearDirI[0] / (float) clearDirCount, now - time > 250); }; - for (int a = 0; a < 9; a++) { + for (int a = 0; a < 10; a++) { if (!selected[a]) { allItemsClear = false; continue; @@ -1011,12 +1026,18 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe clearedSize += cacheTempSize; documentsMusicType = 4; type = FileLoader.MEDIA_DIR_CACHE; + } else if (a == 9) { + clearedSize += logsSize; + documentsMusicType = 1; + type = 0; } if (type == -1) { continue; } File file; - if (type == 100) { + if (a == 9) { + file = AndroidUtilities.getLogsDir(); + } else if (type == 100) { file = new File(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), "acache"); } else { file = FileLoader.checkDirectory(type); @@ -1058,7 +1079,9 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe next.run(); } - if (type == FileLoader.MEDIA_DIR_CACHE) { + if (a == 9) { + logsSize = getDirectorySize(AndroidUtilities.getLogsDir(), 1); + } else if (type == FileLoader.MEDIA_DIR_CACHE) { cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 5); cacheTempSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 4); imagesCleared = true; @@ -1089,7 +1112,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe } } final boolean imagesClearedFinal = imagesCleared; - totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; + totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + logsSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); Arrays.fill(selected, true); @@ -1181,13 +1204,14 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe case 6: return stickersCacheSize; case 7: return cacheSize; case 8: return cacheTempSize; + case 9: return logsSize; default: return 0; } } private int sectionsSelected() { int count = 0; - for (int i = 0; i < 9; ++i) { + for (int i = 0; i < 10; ++i) { if (selected[i] && size(i) > 0) { count++; } @@ -2068,7 +2092,8 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe (selected[5] ? storiesSize : 0) + (selected[6] ? stickersCacheSize : 0) + (selected[7] ? cacheSize : 0) + - (selected[8] ? cacheTempSize : 0) + (selected[8] ? cacheTempSize : 0) + + (selected[9] ? logsSize : 0) ); setSize( isAllSectionsSelected(), @@ -2581,7 +2606,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe final ItemInner item = itemInners.get(position); switch (holder.getItemViewType()) { case VIEW_TYPE_CHART: -// updateChart(); + updateChart(); break; case VIEW_TYPE_CHART_HEADER: if (cacheChartHeader != null && !calculating) { @@ -2668,7 +2693,6 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe headerCell.setTopMargin(itemInners.get(position).headerTopMargin); headerCell.setBottomMargin(itemInners.get(position).headerBottomMargin); break; - } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java index e92aade49..8094bd6ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java @@ -113,7 +113,7 @@ public class AccountSelectCell extends FrameLayout { } else { TLRPC.Chat chat = (TLRPC.Chat) object; avatarDrawable.setInfo(chat); - infoTextView.setText(chat.title); + infoTextView.setText(chat == null ? "" : chat.title); imageView.setForUserOrChat(chat, avatarDrawable); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index 87276ab4e..786b3d4de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -76,6 +76,7 @@ import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChannelAdminLogActivity; import org.telegram.ui.ChatBackgroundDrawable; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -89,16 +90,19 @@ import org.telegram.ui.Components.Premium.StarParticlesView; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; +import org.telegram.ui.ProfileActivity; import org.telegram.ui.Stories.StoriesUtilities; import org.telegram.ui.Stories.UploadingDotsSpannable; import org.telegram.ui.Stories.recorder.HintView2; import org.telegram.ui.Stories.recorder.PreviewView; +import java.nio.channels.Channel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -459,6 +463,17 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (messageObject.type != MessageObject.TYPE_ACTION_WALLPAPER) { wallpaperPreviewDrawable = null; } + if (messageObject.actionDeleteGroupEventId != -1) { + ScaleStateListAnimator.apply(this, .02f, 1.2f); + overriddenMaxWidth = Math.max(dp(250), HintView2.cutInFancyHalf(messageObject.messageText, (TextPaint) getThemedPaint(Theme.key_paint_chatActionText))); + ProfileActivity.ShowDrawable showDrawable = ChannelAdminLogActivity.findDrawable(messageObject.messageText); + if (showDrawable != null) { + showDrawable.setView(this); + } + } else { + ScaleStateListAnimator.reset(this); + overriddenMaxWidth = 0; + } if (messageObject.isStoryMention()) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.media.user_id); avatarDrawable.setInfo(currentAccount, user); @@ -1804,7 +1819,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD int lineWidth = (int) Math.ceil(textLayout.getLineWidth(a)); if (a != 0) { int diff = prevLineWidth - lineWidth; - if (diff > 0 && diff <= corner + cornerIn) { + if (diff > 0 && diff <= 1.5f * corner + cornerIn) { lineWidth = prevLineWidth; } } @@ -1814,7 +1829,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD for (int a = count - 2; a >= 0; a--) { int lineWidth = lineWidths.get(a); int diff = prevLineWidth - lineWidth; - if (diff > 0 && diff <= corner + cornerIn) { + if (diff > 0 && diff <= 1.5f * corner + cornerIn) { lineWidth = prevLineWidth; } lineWidths.set(a, lineWidth); 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 4de2cf352..9be34e40d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -128,6 +128,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.AvatarSpan; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -145,6 +146,7 @@ import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EmptyStubSpan; import org.telegram.ui.Components.FloatSeekBarAccessibilityDelegate; import org.telegram.ui.Components.Forum.MessageTopicButton; +import org.telegram.ui.Components.ForwardBackground; import org.telegram.ui.Components.InfiniteProgress; import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.LinkSpanDrawable; @@ -169,6 +171,7 @@ 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.StickerSetLinkIcon; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TimerParticles; import org.telegram.ui.Components.TranscribeButton; @@ -292,23 +295,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate avatarDrawable.setInfo(currentAccount, currentChat); avatarImage.setForUserOrChat(currentChat, avatarDrawable); } else if (messageObject.isSponsored()) { - if (messageObject.sponsoredWebPage != null) { - avatarDrawable.setInfo(messageObject.sponsoredId[0], messageObject.sponsoredWebPage.site_name, null, null); - TLRPC.Photo photo = messageObject.sponsoredWebPage.photo; - if (photo != null) { - avatarImage.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(50), false, null, true), photo), "50_50", avatarDrawable, null, null, 0); - } - } else if (messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { - avatarDrawable.setInfo(currentAccount, messageObject.sponsoredChatInvite.chat); - avatarImage.setForUserOrChat(messageObject.sponsoredChatInvite.chat, avatarDrawable); - } else { - avatarDrawable.setInfo(currentAccount, messageObject.sponsoredChatInvite); - if (messageObject.sponsoredChatInvite != null) { - TLRPC.Photo photo = messageObject.sponsoredChatInvite.photo; - if (photo != null) { - avatarImage.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(50), false, null, true), photo), "50_50", avatarDrawable, null, null, 0); - } - } + if (messageObject.sponsoredPhoto != null) { + avatarImage.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(messageObject.sponsoredPhoto.sizes, AndroidUtilities.dp(50), false, null, true), messageObject.sponsoredPhoto), "50_50", avatarDrawable, null, null, 0); } } else { currentPhoto = null; @@ -541,7 +529,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressOther(ChatMessageCell cell, float otherX, float otherY) { } - default void didPressSponsoredClose() { + default void didPressSponsoredClose(ChatMessageCell cell) { } default void didPressSponsoredInfo(ChatMessageCell cell, float x, float y) { @@ -559,7 +547,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction, boolean longpress) { } - default void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { + default void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { } default void didPressInstantButton(ChatMessageCell cell, int type) { @@ -765,12 +753,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean prevChosen; private boolean correct; private StaticLayout title; - private TLRPC.TL_pollAnswer answer; + public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmoji; + private TLRPC.PollAnswer answer; } public static final int INSTANT_BUTTON_TYPE_CONTACT_VIEW = 5; public static final int INSTANT_BUTTON_TYPE_CONTACT_SEND_MESSAGE = 30; public static final int INSTANT_BUTTON_TYPE_CONTACT_ADD = 31; + public static final int INSTANT_BUTTON_TYPE_STICKER_SET = 23; + public static final int INSTANT_BUTTON_TYPE_EMOJI_SET = 24; private static class InstantViewButton { private int type; @@ -847,6 +838,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private Paint onceRadialStrokePaint; private int onceRadialPaintColor; + private StickerSetLinkIcon stickerSetIcons; + private boolean disallowLongPress; private float lastTouchX; private float lastTouchY; @@ -861,6 +854,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private long lastCheckBoxAnimationTime; public int checkBoxTranslation; + private AvatarSpan forwardAvatar; + private ForwardBackground forwardBg; public boolean linkPreviewAbove; private boolean isSmallImage; private boolean drawImageButton; @@ -1024,6 +1019,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private BitmapDrawable currentPhotoObjectThumbStripped; private String currentPhotoFilter; private String currentPhotoFilterThumb; + private Drawable foreverDrawable; + private int foreverDrawableColor = 0xFFFFFFFF; private boolean timePressed; @@ -1367,6 +1364,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiStack; public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiReplyStack; public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiDescriptionStack; + public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiPollQuestion; public ButtonBounce replyBounce, contactBounce; public float replyBounceX, replyBounceY; public Drawable replySelector; @@ -2268,7 +2266,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate final float left = descriptionLayout.getLineLeft(line); if (left <= checkX && left + descriptionLayout.getLineWidth(line) >= checkX) { - Spannable buffer = (Spannable) currentMessageObject.linkDescription; + Spannable buffer = (Spannable) (currentMessageObject.isSponsored() ? currentMessageObject.messageText : currentMessageObject.linkDescription); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); boolean ignore = false; if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { @@ -2537,9 +2535,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Toast.makeText(getContext(), LocaleController.getString("MessageScheduledVote", R.string.MessageScheduledVote), Toast.LENGTH_LONG).show(); } else { PollButton button = pollButtons.get(pressedVoteButton); - TLRPC.TL_pollAnswer answer = button.answer; + TLRPC.PollAnswer answer = button.answer; if (pollVoted || pollClosed) { - ArrayList answers = new ArrayList<>(); + ArrayList answers = new ArrayList<>(); answers.add(answer); delegate.didPressVoteButtons(this, answers, button.count, button.x + AndroidUtilities.dp(50), button.y + namesOffset); } else { @@ -2559,7 +2557,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate firstCircleLength = true; voteCurrentCircleLength = 360; voteRisingCircleLength = false; - ArrayList answers = new ArrayList<>(); + ArrayList answers = new ArrayList<>(); answers.add(answer); delegate.didPressVoteButtons(this, answers, -1, 0, 0); } @@ -2829,7 +2827,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (event.getAction() == MotionEvent.ACTION_UP) { if (closeSponsoredBounce != null && closeSponsoredBounce.isPressed()) { if (delegate != null) { - delegate.didPressSponsoredClose(); + delegate.didPressSponsoredClose(this); } } if (closeSponsoredBounce != null) { @@ -3380,7 +3378,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean checkBotButtonMotionEvent(MotionEvent event) { - if (botButtons.isEmpty() || currentMessageObject.eventId != 0) { + if (botButtons.isEmpty()) { return false; } @@ -3669,6 +3667,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (viaWidth != 0 && x >= forwardNameX + viaNameWidth + AndroidUtilities.dp(4)) { forwardBotPressed = true; } else { + if (forwardBg != null) { + forwardBg.setPressed(true, x - forwardNameX, y - forwardNameY); + } forwardNamePressed = true; } result = true; @@ -3760,7 +3761,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate id = 0; } delegate.didPressChannelAvatar(this, chat != null ? chat : currentChat, id, lastTouchX, lastTouchY); - } else if (currentMessageObject != null && currentMessageObject.sponsoredChatInvite != null) { + } else if (currentMessageObject != null) { delegate.didPressInstantButton(this, drawInstantViewType); } } @@ -3784,6 +3785,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (forwardNamePressed) { if (event.getAction() == MotionEvent.ACTION_UP) { forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } playSoundEffect(SoundEffectConstants.CLICK); if (delegate != null) { if (currentForwardChannel != null) { @@ -3800,9 +3804,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { if (!(x >= forwardNameX && x <= forwardNameX + forwardedNameWidth && y >= forwardNameY && y <= forwardNameY + forwardHeight)) { forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } } } } else if (forwardBotPressed) { @@ -3902,7 +3912,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate playSoundEffect(SoundEffectConstants.CLICK); if (delegate != null) { if (pressedSideButton == SIDE_BUTTON_SPONSORED_CLOSE) { - delegate.didPressSponsoredClose(); + delegate.didPressSponsoredClose(this); } else if (pressedSideButton == SIDE_BUTTON_SPONSORED_MORE) { delegate.didPressSponsoredInfo(this, x, y); } else if (pressedSideButton == 3) { @@ -4697,6 +4707,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ImageLoader.getInstance().removeTestWebFile(currentUrl); addedForTest = false; } + if (stickerSetIcons != null) { + stickerSetIcons.detach(this); + } DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); if (getDelegate() != null && getDelegate().getTextSelectionHelper() != null) { @@ -4823,6 +4836,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (channelRecommendationsCell != null) { channelRecommendationsCell.onAttachedToWindow(); } + if (stickerSetIcons != null) { + stickerSetIcons.attach(this); + } } public void copySpoilerEffect2AttachIndexFrom(ChatMessageCell cell) { @@ -5057,6 +5073,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate groupChanged = newPosition != currentPosition; } if (messageChanged || dataChanged || groupChanged || pollChanged || widthChanged && messageObject.isPoll() || isPhotoDataChanged(messageObject) || pinnedBottom != bottomNear || pinnedTop != topNear) { + if (stickerSetIcons != null) { + stickerSetIcons.readyToDie(); + } wasPinned = isPinned; pinnedBottom = bottomNear; pinnedTop = topNear; @@ -5519,6 +5538,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate TLRPC.Document androidThemeDocument = null; TL_stories.StoryItem storyItem = null; TLRPC.ThemeSettings androidThemeSettings = null; + ArrayList stickers = null; + boolean stickersTextColor = false; if (messageObject.isGiveawayOrGiveawayResults()) { hasLinkPreview = true; } @@ -5531,22 +5552,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawInstantView = true; hasLinkPreview = true; instantViewButtonText = messageObject.sponsoredButtonText; - if (messageObject.sponsoredBotApp != null) { - drawInstantViewType = 15; - } else if (messageObject.sponsoredWebPage != null) { - drawInstantViewType = 16; - } else if (messageObject.sponsoredChannelPost != 0) { - drawInstantViewType = 12; - } else { - drawInstantViewType = 1; - long id = MessageObject.getPeerId(messageObject.messageOwner.from_id); - if (id > 0) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(id); - if (user != null && user.bot) { - drawInstantViewType = 10; - } - } - } + drawInstantViewType = 1; } else if (messageObject.isGiveawayOrGiveawayResults()) { drawInstantView = true; drawInstantViewType = 19; @@ -5698,6 +5704,25 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } catch (Exception ignore) { } + } else if ("telegram_stickerset".equals(webpageType)) { + TLRPC.TL_webPageAttributeStickerSet attr = null; + for (int i = 0; i < webpage.attributes.size(); ++i) { + if (webpage.attributes.get(i) instanceof TLRPC.TL_webPageAttributeStickerSet) { + attr = (TLRPC.TL_webPageAttributeStickerSet) webpage.attributes.get(i); + break; + } + } + drawInstantView = true; + if (attr != null && attr.emojis) { + drawInstantViewType = 24; + } else { + drawInstantViewType = 23; + } + isSmallImage = true; + if (attr != null) { + stickers = attr.stickers; + stickersTextColor = attr.text_color; + } } } else if (siteName != null) { siteName = siteName.toLowerCase(); @@ -5840,27 +5865,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photo = null; author = null; document = null; - if (messageObject.sponsoredBotApp != null) { - photo = messageObject.sponsoredBotApp.photo; - } else if (messageObject.sponsoredWebPage != null) { - photo = messageObject.sponsoredWebPage.photo; - } else if (messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { - peerPhoto = messageObject.sponsoredChatInvite.chat; - currentPhotoLocation = ImageLocation.getForChat(messageObject.sponsoredChatInvite.chat, ImageLocation.TYPE_BIG); - currentPhotoThumbLocation = ImageLocation.getForChat(messageObject.sponsoredChatInvite.chat, ImageLocation.TYPE_SMALL); - } else if (messageObject.sponsoredShowPeerPhoto) { - peerPhoto = messageObject.getFromPeerObject(); - if (peerPhoto instanceof TLRPC.User) { - currentPhotoLocation = ImageLocation.getForUser((TLRPC.User) peerPhoto, ImageLocation.TYPE_BIG); - currentPhotoThumbLocation = ImageLocation.getForUser((TLRPC.User) peerPhoto, ImageLocation.TYPE_SMALL); - } else if (peerPhoto instanceof TLRPC.Chat) { - currentPhotoLocation = ImageLocation.getForChat((TLRPC.Chat) peerPhoto, ImageLocation.TYPE_BIG); - currentPhotoThumbLocation = ImageLocation.getForChat((TLRPC.Chat) peerPhoto, ImageLocation.TYPE_SMALL); - } - } - if (photo == null && messageObject.sponsoredChatInvite != null) { - photo = messageObject.sponsoredChatInvite.photo; - } + photo = messageObject.sponsoredPhoto; duration = 0; type = null; isSmallImage = photo != null || peerPhoto != null; @@ -5928,9 +5933,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate "telegram_user".equals(type) || "telegram_channel".equals(type) || "telegram_megagroup".equals(type) || "telegram_voicechat".equals(type) || "telegram_livestream".equals(type) || "telegram_channel_boost".equals(type) || "telegram_group_boost".equals(type); - smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20 || drawInstantViewType == 22) && document == null && isSmallImageType; + smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20 || drawInstantViewType == 22) && document == null && isSmallImageType || (drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty(); TLRPC.MessageMedia media = MessageObject.getMedia(messageObject.messageOwner); - if (media != null) { + if (media != null && !(drawInstantViewType == 23 || drawInstantViewType == 24)) { if (media.force_large_media) { smallImage = false; } @@ -5939,7 +5944,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } linkPreviewAbove = currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.invert_media; - isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null; + isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null || (drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty(); } else if (hasInvoicePreview) { TLRPC.TL_messageMediaInvoice invoice = (TLRPC.TL_messageMediaInvoice) MessageObject.getMedia(messageObject.messageOwner); site_name = MessageObject.getMedia(messageObject.messageOwner).title; @@ -6476,7 +6481,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (documentAttachType != DOCUMENT_ATTACH_TYPE_MUSIC && documentAttachType != DOCUMENT_ATTACH_TYPE_AUDIO && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { - if (currentPhotoObject != null || currentPhotoLocation != null || webDocument != null || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { + if (currentPhotoObject != null || currentPhotoLocation != null || webDocument != null || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_THEME || (drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty()) { drawImageButton = photo != null && !smallImage || type != null && (type.equals("photo") || type.equals("document") && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER || type.equals("gif") || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER); if (isSmallImage) { drawImageButton = false; @@ -6599,7 +6604,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhotoFilter = String.format(Locale.US, "%d_%d", w, h); currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", w, h); - if (webDocument != null) { + if ((drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty()) { + if (stickerSetIcons == null || !stickerSetIcons.equals(stickers)) { + if (stickerSetIcons != null) { + stickerSetIcons.detach(this); + } + stickerSetIcons = new StickerSetLinkIcon(currentAccount, currentMessageObject.isOutOwner(), stickers, stickersTextColor); + if (attachedToWindow) { + stickerSetIcons.attach(this); + } + } + if (stickerSetIcons != null) { + stickerSetIcons.keepAlive(); + } + photoImage.setImageBitmap(stickerSetIcons); + } else if (webDocument != null) { /*TODO*/ photoImage.setImage(ImageLocation.getForWebFile(webDocument), currentPhotoFilter, null, null, webDocument.size, null, messageObject, 1); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { @@ -7086,7 +7105,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (pollVoted) { messageObject.checkedVotes.clear(); } - titleLayout = new StaticLayout(Emoji.replaceEmoji(media.poll.question, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false), Theme.chat_audioTitlePaint, maxWidth + AndroidUtilities.dp(2) - getExtraTextX() * 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + CharSequence questionText = new SpannableStringBuilder(media.poll.question.text); + questionText = Emoji.replaceEmoji(questionText, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false); + if (media.poll.question.entities != null) { + questionText = MessageObject.replaceAnimatedEmoji(questionText, media.poll.question.entities, Theme.chat_audioTitlePaint.getFontMetricsInt(), true); + MessageObject.addEntitiesToText(questionText, media.poll.question.entities, currentMessageObject.isOutOwner(), false, false, false); + } + titleLayout = new StaticLayout(questionText, Theme.chat_audioTitlePaint, maxWidth + AndroidUtilities.dp(2) - getExtraTextX() * 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + animatedEmojiPollQuestion = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, false, animatedEmojiPollQuestion, titleLayout); boolean titleRtl = false; if (titleLayout != null) { for (int a = 0, N = titleLayout.getLineCount(); a < N; a++) { @@ -7226,9 +7252,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean hasDifferent = false; int previousPercent = 0; for (int a = 0, N = media.poll.answers.size(); a < N; a++) { + TLRPC.PollAnswer pollAnswer = media.poll.answers.get(a); + CharSequence answerText = new SpannableStringBuilder(pollAnswer.text.text); + answerText = Emoji.replaceEmoji(answerText, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false); + if (pollAnswer.text.entities != null) { + answerText = MessageObject.replaceAnimatedEmoji(answerText, pollAnswer.text.entities, Theme.chat_audioPerformerPaint.getFontMetricsInt(), true); + MessageObject.addEntitiesToText(answerText, pollAnswer.text.entities, currentMessageObject.isOutOwner(), false, false, false); + } + PollButton button = new PollButton(); - button.answer = media.poll.answers.get(a); - button.title = new StaticLayout(Emoji.replaceEmoji(button.answer.text, Theme.chat_audioPerformerPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false), Theme.chat_audioPerformerPaint, maxWidth - AndroidUtilities.dp(33), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + button.answer = pollAnswer; + button.title = new StaticLayout(answerText, Theme.chat_audioPerformerPaint, maxWidth - AndroidUtilities.dp(33), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + button.animatedEmoji = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, false, button.animatedEmoji, button.title); button.y = height + AndroidUtilities.dp(52); button.height = button.title.getHeight(); pollButtons.add(button); @@ -8937,7 +8972,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!mediaBackground && !currentMessageObject.isOutOwner()) { bl = nearRad; } - if (currentMessageObject.type == MessageObject.TYPE_GEO && MessageObject.getMedia(currentMessageObject) instanceof TLRPC.TL_messageMediaVenue) { + if (currentMessageObject.type == MessageObject.TYPE_GEO && (MessageObject.getMedia(currentMessageObject) instanceof TLRPC.TL_messageMediaVenue || !locationExpired && MessageObject.getMedia(currentMessageObject) instanceof TLRPC.TL_messageMediaGeoLive)) { br = bl = nearRad; } if (documentAttachType == DOCUMENT_ATTACH_TYPE_STORY) { @@ -8946,6 +8981,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setRoundRadius(tl, tr, br, bl); } updateAnimatedEmojis(); + if (stickerSetIcons != null && stickerSetIcons.die()) { + stickerSetIcons.detach(this); + stickerSetIcons = null; + } } if (messageIdChanged) { currentUrl = null; @@ -9155,6 +9194,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (topicButton != null) { topicButton.resetClick(); } + forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } if (pressedEmoji != null) { // hadLongPress = true; // if (delegate.didPressAnimatedEmoji(this, pressedEmoji)) { @@ -10056,10 +10099,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean isCurrentLocationTimeExpired(MessageObject messageObject) { - if (MessageObject.getMedia(currentMessageObject.messageOwner).period % 60 == 0) { - return Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - messageObject.messageOwner.date) > MessageObject.getMedia(messageObject.messageOwner).period; + final int period = MessageObject.getMedia(currentMessageObject.messageOwner).period; + final int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + if (period == 0x7fffffff) { + return false; + } else if (period % 60 == 0) { + return Math.abs(currentTime - messageObject.messageOwner.date) > period; } else { - return Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - messageObject.messageOwner.date) > MessageObject.getMedia(messageObject.messageOwner).period - 5; + return Math.abs(currentTime - messageObject.messageOwner.date) > period - 5; } } @@ -10232,52 +10279,56 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (instantViewButtonText != null) { str = instantViewButtonText; } else if (drawInstantViewType == 12) { - str = LocaleController.getString("OpenChannelPost", R.string.OpenChannelPost); + str = LocaleController.getString(R.string.OpenChannelPost); } else if (drawInstantViewType == 1) { - str = LocaleController.getString("OpenChannel", R.string.OpenChannel); + str = LocaleController.getString(R.string.OpenChannel); } else if (drawInstantViewType == 13) { - str = LocaleController.getString("SendMessage", R.string.SendMessage).toUpperCase(); + str = LocaleController.getString(R.string.SendMessage).toUpperCase(); } else if (drawInstantViewType == 10) { - str = LocaleController.getString("OpenBot", R.string.OpenBot); + str = LocaleController.getString(R.string.OpenBot); } else if (drawInstantViewType == 2) { - str = LocaleController.getString("OpenGroup", R.string.OpenGroup); + str = LocaleController.getString(R.string.OpenGroup); } else if (drawInstantViewType == 3) { - str = LocaleController.getString("OpenMessage", R.string.OpenMessage); + str = LocaleController.getString(R.string.OpenMessage); } else if (drawInstantViewType == 5) { - str = LocaleController.getString("ViewContact", R.string.ViewContact); + str = LocaleController.getString(R.string.ViewContact); } else if (drawInstantViewType == 6) { - str = LocaleController.getString("OpenBackground", R.string.OpenBackground); + str = LocaleController.getString(R.string.OpenBackground); } else if (drawInstantViewType == 7) { - str = LocaleController.getString("OpenTheme", R.string.OpenTheme); + str = LocaleController.getString(R.string.OpenTheme); } else if (drawInstantViewType == 8) { if (pollVoted || pollClosed) { - str = LocaleController.getString("PollViewResults", R.string.PollViewResults); + str = LocaleController.getString(R.string.PollViewResults); } else { - str = LocaleController.getString("PollSubmitVotes", R.string.PollSubmitVotes); + str = LocaleController.getString(R.string.PollSubmitVotes); } } else if (drawInstantViewType == 9 || drawInstantViewType == 11) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) MessageObject.getMedia(currentMessageObject.messageOwner).webpage; if (webPage != null && webPage.url.contains("voicechat=")) { - str = LocaleController.getString("VoipGroupJoinAsSpeaker", R.string.VoipGroupJoinAsSpeaker); + str = LocaleController.getString(R.string.VoipGroupJoinAsSpeaker); } else { - str = LocaleController.getString("VoipGroupJoinAsLinstener", R.string.VoipGroupJoinAsLinstener); + str = LocaleController.getString(R.string.VoipGroupJoinAsLinstener); } } else if (drawInstantViewType == 14) { - str = LocaleController.getString("ViewChatList", R.string.ViewChatList).toUpperCase(); + str = LocaleController.getString(R.string.ViewChatList).toUpperCase(); } else if (drawInstantViewType == 15) { str = LocaleController.getString(R.string.BotWebAppInstantViewOpen).toUpperCase(); } else if (drawInstantViewType == 16) { - str = LocaleController.getString("OpenLink").toUpperCase(); + str = LocaleController.getString(R.string.OpenLink).toUpperCase(); } else if (drawInstantViewType == 17) { - str = LocaleController.getString("ViewStory").toUpperCase(); + str = LocaleController.getString(R.string.ViewStory).toUpperCase(); } else if (drawInstantViewType == 18 || drawInstantViewType == 22) { - str = LocaleController.getString("BoostLinkButton", R.string.BoostLinkButton); + str = LocaleController.getString(R.string.BoostLinkButton); } else if (drawInstantViewType == 19) { - str = LocaleController.getString("BoostingHowItWork", R.string.BoostingHowItWork); + str = LocaleController.getString(R.string.BoostingHowItWork); } else if (drawInstantViewType == 20) { str = LocaleController.getString(R.string.OpenGift); } else if (drawInstantViewType == 21) { str = LocaleController.getString(R.string.AppUpdate); + } else if (drawInstantViewType == 23) { + str = LocaleController.getString(R.string.OpenStickerSet); + } else if (drawInstantViewType == 24) { + str = LocaleController.getString(R.string.OpenEmojiSet); } else { str = LocaleController.getString(R.string.InstantView); } @@ -11990,6 +12041,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkLine = new ReplyMessageLine(this); } Theme.chat_replyNamePaint.setColor(linkLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, ReplyMessageLine.TYPE_LINK)); + linkLine.setEmojiAlpha(drawInstantViewType == 23 || drawInstantViewType == 24 ? 0.5f : 1f); final boolean drawPhotoImageBefore = drawInstantView && (drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18 && drawInstantViewType != 22) || drawInstantViewType == 6 && imageBackgroundColor != 0; final boolean drawPhotoImageAfter = !drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18 || drawInstantViewType == 22 || isSmallImage; @@ -14884,33 +14936,50 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageObject.type == MessageObject.TYPE_STORY || currentForwardUser != null || currentForwardChannel != null || currentForwardName != null) { String forwardedString; CharSequence lastLine; + if (forwardAvatar == null) { + forwardAvatar = new AvatarSpan(this, currentAccount); + forwardAvatar.translate(0, dp(-.33f)); + } + forwardAvatar.setSize((1.23f * ((int) Theme.chat_forwardNamePaint.getTextSize())) / AndroidUtilities.density); if (messageObject.type == MessageObject.TYPE_STORY) { - currentForwardNameString = forwardedString = LocaleController.getString("ForwardedStory", R.string.ForwardedStory); + currentForwardNameString = forwardedString = LocaleController.getString(R.string.ForwardedStory); long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer); if (storyDialogId > 0) { - currentForwardUser = MessagesController.getInstance(currentAccount).getUser(storyDialogId); + forwardAvatar.setUser(currentForwardUser = MessagesController.getInstance(currentAccount).getUser(storyDialogId)); } else { - currentForwardChannel = MessagesController.getInstance(currentAccount).getChat(-storyDialogId); + forwardAvatar.setChat(currentForwardChannel = MessagesController.getInstance(currentAccount).getChat(-storyDialogId)); } + boolean includeAvatar = true; String name = getNameFromDialogId(storyDialogId); if (storyDialogId < 0 && currentForwardChannel == null) { name = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate); + includeAvatar = false; + } + lastLine = new SpannableStringBuilder((includeAvatar ? "A " : "") + name); + ((SpannableStringBuilder) lastLine).setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, lastLine.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (includeAvatar) { + ((SpannableStringBuilder) lastLine).setSpan(forwardAvatar, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - lastLine = AndroidUtilities.replaceTags(LocaleController.formatString("ForwardedStoryFrom", R.string.ForwardedStoryFrom, name)); forwardedNameWidth = getMaxNameWidth(); } else { + boolean includeAvatar = true; if (currentForwardChannel != null) { if (currentForwardUser != null) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, UserObject.getUserName(currentForwardUser)); + forwardAvatar.setUser(currentForwardUser); } else if (!TextUtils.isEmpty(messageObject.messageOwner.fwd_from.post_author)) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, messageObject.messageOwner.fwd_from.post_author); + forwardAvatar.setChat(currentForwardChannel); } else { currentForwardNameString = currentForwardChannel.title; + forwardAvatar.setChat(currentForwardChannel); } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); + forwardAvatar.setUser(currentForwardUser); } else { currentForwardNameString = currentForwardName; + includeAvatar = false; } forwardedNameWidth = getMaxNameWidth(); @@ -14918,17 +14987,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasPsaHint) { forwardedNameWidth -= AndroidUtilities.dp(36); } - String from = LocaleController.getString("From", R.string.From); - String fromFormattedString = LocaleController.getString("FromFormatted", R.string.FromFormatted); - int idx = fromFormattedString.indexOf("%1$s"); - int fromWidth = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(from + " ")); - CharSequence name = TextUtils.ellipsize(currentForwardNameString.replace('\n', ' '), Theme.chat_replyNamePaint, forwardedNameWidth - fromWidth - viaWidth, TextUtils.TruncateAt.END); - String fromString; - try { - fromString = String.format(fromFormattedString, name); - } catch (Exception e) { - fromString = name.toString(); - } + CharSequence name = TextUtils.ellipsize((includeAvatar ? "A " : "") + currentForwardNameString.replace('\n', ' '), Theme.chat_replyNamePaint, forwardedNameWidth - viaWidth - dp(includeAvatar ? 17.33f : 0), TextUtils.TruncateAt.END); + String fromString = name.toString(); SpannableStringBuilder stringBuilder; if (viaString != null) { @@ -14936,11 +14996,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate viaNameWidth = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(fromString)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), stringBuilder.length() - viaUsername.length() - 1, stringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } else { - stringBuilder = new SpannableStringBuilder(String.format(fromFormattedString, name)); + stringBuilder = new SpannableStringBuilder(fromString); } - forwardNameCenterX = fromWidth + (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(name, 0, name.length())) / 2; - if (idx >= 0 && (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null)) { - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), idx, idx + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + if (includeAvatar && stringBuilder.length() > 1) { + stringBuilder.setSpan(forwardAvatar, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + forwardNameCenterX = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(name, 0, name.length())) / 2; + if (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null) { + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } lastLine = stringBuilder; } @@ -14953,6 +15016,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate forwardedNameLayout[1] = new StaticLayout(lastLine, Theme.chat_forwardNamePaint, forwardedNameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); lastLine = TextUtils.ellipsize(AndroidUtilities.replaceTags(forwardedString), Theme.chat_forwardNamePaint, forwardedNameWidth, TextUtils.TruncateAt.END); forwardedNameLayout[0] = new StaticLayout(lastLine, Theme.chat_forwardNamePaint, forwardedNameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (forwardBg == null) { + forwardBg = new ForwardBackground(this); + } + forwardBg.set(forwardedNameLayout, !currentMessageObject.isOutOwner() && !(drawNameLayout && nameLayout != null) && pinnedTop); forwardedNameWidth = Math.max((int) Math.ceil(forwardedNameLayout[0].getLineWidth(0)), (int) Math.ceil(forwardedNameLayout[1].getLineWidth(0))); if (hasPsaHint) { forwardedNameWidth += AndroidUtilities.dp(36); @@ -15249,30 +15316,39 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (currentForwardUser != null || currentForwardChannel != null || currentForwardName != null) { + if (forwardAvatar == null) { + forwardAvatar = new AvatarSpan(this, currentAccount); + forwardAvatar.translate(0, dp(-.33f)); + } + forwardAvatar.setSize((1.23f * ((int) Theme.chat_forwardNamePaint.getTextSize())) / AndroidUtilities.density); + boolean includeAvatar = true; if (currentForwardChannel != null) { if (currentForwardUser != null) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, UserObject.getUserName(currentForwardUser)); + forwardAvatar.setUser(currentForwardUser); } else { currentForwardNameString = currentForwardChannel.title; + forwardAvatar.setChat(currentForwardChannel); } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); + forwardAvatar.setUser(currentForwardUser); } else { currentForwardNameString = currentForwardName; + includeAvatar = false; } name = getForwardedMessageText(messageObject); - String from = LocaleController.getString("From", R.string.From); - String fromFormattedString = LocaleController.getString("FromFormatted", R.string.FromFormatted); - int idx = fromFormattedString.indexOf("%1$s"); - int fromWidth = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(from + " ")); CharSequence text = currentForwardNameString == null ? "" : currentForwardNameString.replace('\n', ' '); - CharSequence ellipsizedText = TextUtils.ellipsize(text, Theme.chat_replyNamePaint, maxWidth - fromWidth, TextUtils.TruncateAt.END); - SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format(fromFormattedString, ellipsizedText)); - if (idx >= 0 && (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null)) { - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), idx, idx + ellipsizedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + CharSequence ellipsizedText = TextUtils.ellipsize((includeAvatar ? "A " : "") + text, Theme.chat_replyNamePaint, maxWidth - dp(includeAvatar ? 17.33f : 0), TextUtils.TruncateAt.END); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(ellipsizedText); + if (includeAvatar && stringBuilder.length() > 1) { + stringBuilder.setSpan(forwardAvatar, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null) { + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, ellipsizedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } stringFinalText = TextUtils.ellipsize(stringBuilder, textPaint, maxWidth, TextUtils.TruncateAt.END); - forwardNameCenterX = fromWidth + (int) Math.ceil(Theme.chat_replyNamePaint.measureText(ellipsizedText, 0, ellipsizedText.length())) / 2; + forwardNameCenterX = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(ellipsizedText, 0, ellipsizedText.length())) / 2; } } CharSequence stringFinalName = name; @@ -15442,19 +15518,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentChat != null) { return currentChat.title; } else if (currentMessageObject != null && currentMessageObject.isSponsored()) { - if (currentMessageObject.sponsoredBotApp != null) { - return currentMessageObject.sponsoredBotApp.title; - } - if (currentMessageObject.sponsoredWebPage != null) { - return currentMessageObject.sponsoredWebPage.site_name; - } - if (currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.title != null) { - return currentMessageObject.sponsoredChatInvite.title; - } - if (currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null && currentMessageObject.sponsoredChatInvite.chat.title != null) { - return currentMessageObject.sponsoredChatInvite.chat.title; - } - return ""; + return currentMessageObject.sponsoredTitle; } return "DELETED"; } @@ -15479,7 +15543,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } return forwardedString; } else { - return LocaleController.getString("ForwardedMessage", R.string.ForwardedMessage); + return LocaleController.getString(R.string.ForwardedFrom); } } @@ -15619,12 +15683,43 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override public int getBoundsLeft() { - return Math.max(0, getBackgroundDrawableLeft() - (needDrawAvatar() ? dp(currentPosition != null ? 73 : (currentMessageObject != null && currentMessageObject.isRepostPreview ? 42 : 63)) : 0) - (currentMessageObject != null && currentMessageObject.isOutOwner() && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0)); + boolean isOut = currentMessageObject != null && currentMessageObject.isOutOwner(); + int avatarWidth = needDrawAvatar() ? dp(currentPosition != null ? 73 : (currentMessageObject != null && currentMessageObject.isRepostPreview ? 42 : 63)) : 0; + int shareButtonWidth = (isOut && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0); + int buttonMostLeft = Integer.MAX_VALUE; + if (botButtons != null) { + int addX; + if (currentMessageObject != null && currentMessageObject.isOutOwner()) { + addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + } else { + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 1 : 7); + } + for (int i = 0; i < botButtons.size(); ++i) { + BotButton btn = botButtons.get(i); + buttonMostLeft = Math.max(buttonMostLeft, addX + btn.x); + } + } + return Math.max(0, Math.min(buttonMostLeft, getBackgroundDrawableLeft() - avatarWidth - shareButtonWidth)); } @Override public int getBoundsRight() { - return getBackgroundDrawableRight() + (currentMessageObject != null && !currentMessageObject.isOutOwner() && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0); + boolean isIn = currentMessageObject != null && !currentMessageObject.isOutOwner(); + int shareButtonWidth = (isIn && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0); + int buttonMostRight = 0; + if (botButtons != null) { + int addX; + if (currentMessageObject != null && currentMessageObject.isOutOwner()) { + addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + } else { + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 1 : 7); + } + for (int i = 0; i < botButtons.size(); ++i) { + BotButton btn = botButtons.get(i); + buttonMostRight = Math.max(buttonMostRight, addX + btn.x + btn.width); + } + } + return Math.max(getBackgroundDrawableRight() + shareButtonWidth, buttonMostRight); } @SuppressLint("WrongCall") @@ -16469,16 +16564,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentMessageObject.overrideLinkColor >= 0 || currentMessageObject.isFromUser() && currentUser != null || currentMessageObject.isFromChannel() && currentChat != null || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null + currentMessageObject.sponsoredColor != null && currentMessageObject.sponsoredColor.color != -1 ) { int colorId; if (currentMessageObject.overrideLinkColor >= 0) { colorId = currentMessageObject.overrideLinkColor; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { - colorId = currentMessageObject.sponsoredChatInvite.color; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null) { - colorId = ChatObject.getColorId(currentMessageObject.sponsoredChatInvite.chat); + } else if (currentMessageObject.sponsoredColor != null) { + colorId = currentMessageObject.sponsoredColor.color; } else if (currentMessageObject.isFromUser() && currentUser != null) { colorId = UserObject.getColorId(currentUser); } else { @@ -17063,17 +17155,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if ( currentMessageObject.overrideLinkColor >= 0 || currentMessageObject.isFromUser() && currentUser != null || - currentMessageObject.isFromChannel() && currentChat != null || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null + currentMessageObject.isFromChannel() && currentChat != null ) { int colorId; if (currentMessageObject.overrideLinkColor >= 0) { colorId = currentMessageObject.overrideLinkColor; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { - colorId = currentMessageObject.sponsoredChatInvite.color; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null) { - colorId = ChatObject.getColorId(currentMessageObject.sponsoredChatInvite.chat); } else if (currentMessageObject.isFromUser() && currentUser != null) { colorId = UserObject.getColorId(currentUser); } else { @@ -17298,19 +17384,40 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), (int) forwardNameXLocal - AndroidUtilities.dp(7) + backWidth, forwardNameY + forwardHeight + AndroidUtilities.dp(6)); } - applyServiceShaderMatrix(); int oldAlpha1 = -1, oldAlpha2 = -1; - if (animatingAlpha != 1f || replyForwardAlpha != 1f) { - oldAlpha1 = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); - getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha1 * animatingAlpha * replyForwardAlpha)); - } - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), getThemedPaint(Theme.key_paint_chatActionBackground)); - if (hasGradientService()) { + if (hasReply || forwardBg == null) { + applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); if (animatingAlpha != 1f || replyForwardAlpha != 1f) { - oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); - Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * animatingAlpha * replyForwardAlpha)); + oldAlpha1 = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); + getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha1 * animatingAlpha * replyForwardAlpha)); } - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_actionBackgroundGradientDarkenPaint); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), getThemedPaint(Theme.key_paint_chatActionBackground)); + if (hasGradientService()) { + if (animatingAlpha != 1f || replyForwardAlpha != 1f) { + oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); + Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * animatingAlpha * replyForwardAlpha)); + } + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_actionBackgroundGradientDarkenPaint); + } + } else { + applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX() + forwardNameXLocal, viewTop + forwardNameY); + canvas.save(); + canvas.translate(forwardNameXLocal, forwardNameY); + final float s = forwardBg.bounce.getScale(.02f); + canvas.scale(s, s, forwardBg.cx, forwardBg.cy); + if (animatingAlpha != 1f || replyForwardAlpha != 1f) { + oldAlpha1 = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); + getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha1 * animatingAlpha * replyForwardAlpha)); + } + canvas.drawPath(forwardBg.path, getThemedPaint(Theme.key_paint_chatActionBackground)); + if (hasGradientService()) { + if (animatingAlpha != 1f || replyForwardAlpha != 1f) { + oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); + Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * animatingAlpha * replyForwardAlpha)); + } + canvas.drawPath(forwardBg.path, Theme.chat_actionBackgroundGradientDarkenPaint); + } + canvas.restore(); } if (oldAlpha1 >= 0) { getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha(oldAlpha1); @@ -17319,7 +17426,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(oldAlpha2); } } else { - forwardNameY = AndroidUtilities.dp(10) + (drawNameLayout ? AndroidUtilities.dp(5) + (int) Theme.chat_namePaint.getTextSize() : 0) + (drawTopic && topicButton != null ? topicButton.height() + AndroidUtilities.dp(7 + (currentMessageObject.type != MessageObject.TYPE_TEXT ? 3 : 0)) : 0); + forwardNameY = AndroidUtilities.dp(7) + (drawNameLayout ? AndroidUtilities.dp(6) + (int) Theme.chat_namePaint.getTextSize() : 0) + (drawTopic && topicButton != null ? topicButton.height() + AndroidUtilities.dp(7 + (currentMessageObject.type != MessageObject.TYPE_TEXT ? 3 : 0)) : 0); + if (!drawNameLayout && (currentMessageObject.type == MessageObject.TYPE_GIF || currentMessageObject.type == MessageObject.TYPE_PHOTO || currentMessageObject.type == MessageObject.TYPE_VIDEO || currentMessageObject.type == MessageObject.TYPE_STORY)) { + forwardNameY += dp(2); + } + if (!drawNameLayout && currentMessageObject.type == MessageObject.TYPE_TEXT && !drawPinnedTop) { + forwardNameY += dp(2); + } forwardHeight = AndroidUtilities.dp(4) + (int) Theme.chat_forwardNamePaint.getTextSize() * 2; Theme.chat_forwardNamePaint.setColor(getThemedColor(hasPsaHint ? Theme.key_chat_inPsaNameText : Theme.key_chat_inForwardedNameText)); if (currentMessageObject.isOutOwner()) { @@ -17355,14 +17468,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (currentMessageObject.isOutOwner()) { if (currentMessageObject.needDrawForwarded()) { - forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(11) + getExtraTextX(); + forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(10) + getExtraTextX(); forwardNameXLocal += transitionParams.deltaLeft; } else { forwardNameXLocal = transitionParams.animateForwardNameX; } } else { if (currentMessageObject.needDrawForwarded()) { - forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 11 : 17) + getExtraTextX(); + forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 10 : 16) + getExtraTextX(); } else { forwardNameXLocal = transitionParams.animateForwardNameX; } @@ -17388,9 +17501,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } + canvas.save(); + canvas.translate(forwardNameXLocal, forwardNameY); + if (forwardBg != null) { + final float s = forwardBg.bounce.getScale(.02f); + canvas.scale(s, s, forwardBg.cx, forwardBg.cy); + if (currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO || currentMessageObject.isAnyKindOfSticker()) { + forwardBg.setColor(Theme.multAlpha(Theme.getColor(Theme.key_listSelector, resourcesProvider), 1.35f)); + } else { + forwardBg.setColor(Theme.multAlpha(Theme.chat_forwardNamePaint.getColor(), .15f)); + } + forwardBg.draw(canvas); + } for (int a = 0; a < 2; a++) { canvas.save(); - canvas.translate(forwardNameXLocal - forwardNameOffsetX[a], forwardNameY + (forwardHeight / 2f + 2) * a); + canvas.translate(-forwardNameOffsetX[a], (forwardHeight / 2f + dp(1.33f)) * a); if (animatingAlpha != 1f || replyForwardAlpha != 1f) { int oldAlpha = forwardedNameLayoutLocal[a].getPaint().getAlpha(); forwardedNameLayoutLocal[a].getPaint().setAlpha((int) (oldAlpha * animatingAlpha * replyForwardAlpha)); @@ -17401,6 +17526,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } canvas.restore(); } + canvas.restore(); if (clipContent) { canvas.restore(); } @@ -17569,9 +17695,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate forwardNameX = replyStartX - replyTextOffset + offset + (needReplyImage ? offset + AndroidUtilities.dp(25) : 0); if ((currentPosition == null || currentPosition.minY == 0 && currentPosition.minX == 0) && !(enterTransitionInProgress && !currentMessageObject.isVoice())) { int restoreToCount = -1; - if (getAlpha() * replyForwardAlpha != 1f) { + float _alpha = (transitionParams.ignoreAlpha ? 1f : getAlpha()) * replyForwardAlpha; + if (_alpha != 1f) { AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); - restoreToCount = canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (0xFF * getAlpha() * replyForwardAlpha), Canvas.ALL_SAVE_FLAG); + restoreToCount = canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (0xFF * _alpha), Canvas.ALL_SAVE_FLAG); } float leftRad, rightRad, bottomRad = Math.min(4f, SharedConfig.bubbleRadius); @@ -19685,12 +19812,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate StaticLayout docTitleLayout = this.docTitleLayout; StaticLayout infoLayout = this.infoLayout; float alpha = 1f; + boolean forever = false; if (transitionParams.animateLocationIsExpired) { progress = transitionParams.lastDrawLocationExpireProgress; text = transitionParams.lastDrawLocationExpireText; docTitleLayout = transitionParams.lastDrawDocTitleLayout; infoLayout = transitionParams.lastDrawInfoLayout; alpha = 1f - transitionParams.animateChangeProgress; + } else if (MessageObject.getMedia(currentMessageObject.messageOwner).period == 0x7fffffff) { + forever = true; + progress = 1.0f; + text = ""; } else { progress = 1.0f - Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date) / (float) MessageObject.getMedia(currentMessageObject.messageOwner).period; text = LocaleController.formatLocationLeftTime(Math.abs(MessageObject.getMedia(currentMessageObject.messageOwner).period - (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date))); @@ -19721,8 +19853,29 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_radialProgress2Paint.setAlpha((int) (255 * alpha)); canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); - float w = Theme.chat_livePaint.measureText(text); - canvas.drawText(text, rect.centerX() - w / 2, cy + AndroidUtilities.dp(4), Theme.chat_livePaint); + if (forever) { + if (foreverDrawable == null) { + foreverDrawable = getContext().getResources().getDrawable(R.drawable.filled_location_forever).mutate(); + } + if (Theme.chat_livePaint.getColor() != foreverDrawableColor) { + foreverDrawable.setColorFilter(new PorterDuffColorFilter(foreverDrawableColor = Theme.chat_livePaint.getColor(), PorterDuff.Mode.SRC_IN)); + } + foreverDrawable.setBounds( + (int) rect.centerX() - foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() - foreverDrawable.getIntrinsicHeight() / 2, + (int) rect.centerX() + foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() + foreverDrawable.getIntrinsicHeight() / 2 + ); + foreverDrawable.draw(canvas); + } else { + float w = Theme.chat_livePaint.measureText(text); + int len = text.length(); + final float s2 = (len > 4 ? .75f : (len > 3 ? .85f : 1f)); + canvas.save(); + canvas.scale(s2, s2, rect.centerX(), rect.centerY()); + canvas.drawText(text, rect.centerX() - w / 2, cy + AndroidUtilities.dp(4), Theme.chat_livePaint); + canvas.restore(); + } if (docTitleLayout != null && infoLayout != null) { canvas.save(); @@ -19895,6 +20048,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.save(); canvas.translate(x + getExtraTextX(), AndroidUtilities.dp(15) + namesOffset); titleLayout.draw(canvas); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, titleLayout, animatedEmojiPollQuestion, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(1, titleLayout.getPaint().getColor())); canvas.restore(); } int y = (titleLayout != null ? titleLayout.getHeight() : 0) + AndroidUtilities.dp(20) + namesOffset; @@ -20025,6 +20179,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.save(); canvas.translate(x + AndroidUtilities.dp(35), button.y + namesOffset); button.title.draw(canvas); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, button.title, button.animatedEmoji, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(1, button.title.getPaint().getColor())); int alpha = (int) (animatePollAnswerAlpha ? 255 * Math.min((pollUnvoteInProgress ? 1.0f - pollAnimationProgress : pollAnimationProgress) / 0.3f, 1.0f) : 255); if (pollVoted || pollClosed || animatePollAnswerAlpha) { if (lastPoll.quiz && pollVoted && button.chosen) { @@ -20930,7 +21085,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (lastPoll != null) { sb.append(", "); - sb.append(lastPoll.question); + sb.append(lastPoll.question.text); sb.append(", "); String title; if (pollClosed) { @@ -21585,7 +21740,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } PollButton button = pollButtons.get(buttonIndex); if (delegate != null) { - ArrayList answers = new ArrayList<>(); + ArrayList answers = new ArrayList<>(); answers.add(button.answer); delegate.didPressVoteButtons(ChatMessageCell.this, answers, -1, 0, 0); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java index f9525da00..ecd8ffb81 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java @@ -8,6 +8,9 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -19,14 +22,28 @@ import android.view.Gravity; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -40,20 +57,31 @@ public class CheckBoxCell extends FrameLayout { TYPE_CHECK_BOX_ENTER_PHONE = 2, TYPE_CHECK_BOX_UNKNOWN = 3, TYPE_CHECK_BOX_ROUND = 4, - TYPE_CHECK_BOX_URL = 5; + TYPE_CHECK_BOX_URL = 5, + TYPE_CHECK_BOX_USER_GROUP = 6, + TYPE_CHECK_BOX_USER = 7, + TYPE_CHECK_BOX_ROUND_GROUP = 8; + + public int itemId; private final Theme.ResourcesProvider resourcesProvider; - private final LinkSpanDrawable.LinksTextView textView; + private LinkSpanDrawable.LinksTextView linksTextView; + private AnimatedTextView animatedTextView; + private View textView; private final TextView valueTextView; private final View checkBox; private CheckBoxSquare checkBoxSquare; private CheckBox2 checkBoxRound; private View collapsedArrow; + private CollapseButton collapseButton; + private BackupImageView avatarImageView; + private AvatarDrawable avatarDrawable; private final int currentType; private final int checkBoxSize; private boolean needDivider; private boolean isMultiline; + private boolean textAnimated; public CheckBoxCell(Context context, int type) { this(context, type, 17, null); @@ -64,42 +92,91 @@ public class CheckBoxCell extends FrameLayout { } public CheckBoxCell(Context context, int type, int padding, Theme.ResourcesProvider resourcesProvider) { + this(context, type, padding, false, resourcesProvider); + } + + public CheckBoxCell(Context context, int type, int padding, boolean textAnimated, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.currentType = type; + this.textAnimated = textAnimated; - textView = new LinkSpanDrawable.LinksTextView(context) { - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - updateCollapseArrowTranslation(); + if (textAnimated) { + animatedTextView = new AnimatedTextView(context) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + updateCollapseArrowTranslation(); + } + }; + NotificationCenter.listenEmojiLoading(animatedTextView); + animatedTextView.setEllipsizeByGradient(true); + animatedTextView.setRightPadding(dp(8)); + animatedTextView.getDrawable().setHacks(true, true, false); + animatedTextView.setTag(getThemedColor(type == TYPE_CHECK_BOX_DEFAULT || type == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + animatedTextView.setTextSize(dp(16)); + if (type == TYPE_CHECK_BOX_USER) { + animatedTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); } - - @Override - public void setText(CharSequence text, BufferType type) { - text = Emoji.replaceEmoji(text, getPaint().getFontMetricsInt(), false); - super.setText(text, type); - } - }; - NotificationCenter.listenEmojiLoading(textView); - textView.setTag(getThemedColor(type == TYPE_CHECK_BOX_DEFAULT || type == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - textView.setLines(1); - textView.setMaxLines(1); - textView.setSingleLine(true); - textView.setEllipsize(TextUtils.TruncateAt.END); - if (type == TYPE_CHECK_BOX_UNKNOWN) { - textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 29, 0, 0, 0)); - textView.setPadding(0, 0, 0, AndroidUtilities.dp(3)); - } else { - textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - if (type == TYPE_CHECK_BOX_ENTER_PHONE) { - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 8 : 29), 0, (LocaleController.isRTL ? 29 : 8), 0)); + if (type == TYPE_CHECK_BOX_UNKNOWN) { + animatedTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 29, 0, 0, 0)); + animatedTextView.setPadding(0, 0, 0, dp(3)); } else { - int offset = type == TYPE_CHECK_BOX_ROUND ? 56 : 46; - addView(textView, LayoutHelper.createFrame(type == TYPE_CHECK_BOX_ROUND ? LayoutHelper.WRAP_CONTENT : LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? padding : offset + (padding - 17)), 0, (LocaleController.isRTL ? offset + (padding - 17) : padding), 0)); + animatedTextView.setRightPadding(dp(padding)); + animatedTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + if (type == TYPE_CHECK_BOX_ENTER_PHONE) { + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 8 : 29), 0, (LocaleController.isRTL ? 29 : 8), 0)); + } else { + int offset = isCheckboxRound() ? 56 : 46; + if (type == TYPE_CHECK_BOX_USER) { + offset += 39; + } + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? padding : offset + (padding - 17)), 0, (LocaleController.isRTL ? offset + (padding - 17) : padding), 0)); + } } + textView = animatedTextView; + } else { + linksTextView = new LinkSpanDrawable.LinksTextView(context) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + updateCollapseArrowTranslation(); + } + + @Override + public void setText(CharSequence text, BufferType type) { + text = Emoji.replaceEmoji(text, getPaint().getFontMetricsInt(), false); + super.setText(text, type); + } + }; + NotificationCenter.listenEmojiLoading(linksTextView); + linksTextView.setTag(getThemedColor(type == TYPE_CHECK_BOX_DEFAULT || type == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + linksTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + linksTextView.setLines(1); + linksTextView.setMaxLines(1); + linksTextView.setSingleLine(true); + linksTextView.setEllipsize(TextUtils.TruncateAt.END); + if (type == TYPE_CHECK_BOX_USER) { + linksTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + } + if (type == TYPE_CHECK_BOX_UNKNOWN) { + linksTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + addView(linksTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 29, 0, 0, 0)); + linksTextView.setPadding(0, 0, 0, dp(3)); + } else { + linksTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + if (type == TYPE_CHECK_BOX_ENTER_PHONE) { + addView(linksTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 8 : 29), 0, (LocaleController.isRTL ? 29 : 8), 0)); + } else { + int offset = isCheckboxRound() ? 56 : 46; + if (type == TYPE_CHECK_BOX_USER) { + offset += 39; + } + addView(linksTextView, LayoutHelper.createFrame(isCheckboxRound() ? LayoutHelper.WRAP_CONTENT : LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? padding : offset + (padding - 17)), 0, (LocaleController.isRTL ? offset + (padding - 17) : padding), 0)); + } + } + textView = linksTextView; } valueTextView = new TextView(context); @@ -112,7 +189,7 @@ public class CheckBoxCell extends FrameLayout { valueTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, padding, 0, padding, 0)); - if (type == TYPE_CHECK_BOX_ROUND) { + if (isCheckboxRound()) { checkBox = checkBoxRound = new CheckBox2(context, 21, resourcesProvider); checkBoxRound.setDrawUnchecked(true); checkBoxRound.setChecked(true, false); @@ -132,18 +209,43 @@ public class CheckBoxCell extends FrameLayout { addView(checkBox, LayoutHelper.createFrame(checkBoxSize, checkBoxSize, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 0 : padding), 16, (LocaleController.isRTL ? padding : 0), 0)); } } + + if (type == TYPE_CHECK_BOX_USER_GROUP) { + collapseButton = new CollapseButton(context, R.drawable.msg_folders_groups); + addView(collapseButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.END | Gravity.CENTER_VERTICAL, padding, 0, padding - 11, 0)); + } else if (type == TYPE_CHECK_BOX_ROUND_GROUP) { + collapseButton = new CollapseButton(context, 0); + addView(collapseButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.END | Gravity.CENTER_VERTICAL, padding, 0, padding - 11, 0)); + } else if (type == TYPE_CHECK_BOX_USER) { + avatarDrawable = new AvatarDrawable(); + avatarImageView = new BackupImageView(context); + avatarImageView.setRoundRadius(dp(17)); + addView(avatarImageView, LayoutHelper.createFrameRelatively(34, 34, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 0, 0)); + } + updateTextColor(); } + public boolean isCheckboxRound() { + return currentType == TYPE_CHECK_BOX_ROUND || currentType == TYPE_CHECK_BOX_ROUND_GROUP || currentType == TYPE_CHECK_BOX_USER_GROUP || currentType == TYPE_CHECK_BOX_USER; + } + public void allowMultiline() { - textView.setLines(3); - textView.setMaxLines(3); - textView.setSingleLine(false); + if (textAnimated) { + return; + } + linksTextView.setLines(3); + linksTextView.setMaxLines(3); + linksTextView.setSingleLine(false); } public void updateTextColor() { - textView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); - textView.setLinkTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextLink : Theme.key_windowBackgroundWhiteLinkText)); + if (textAnimated) { + animatedTextView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + } else { + linksTextView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + linksTextView.setLinkTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextLink : Theme.key_windowBackgroundWhiteLinkText)); + } valueTextView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlue : Theme.key_windowBackgroundWhiteValueText)); } @@ -210,9 +312,9 @@ public class CheckBoxCell extends FrameLayout { float translateX; if (LocaleController.isRTL) { - translateX = textView.getRight() - textWidth - AndroidUtilities.dp(20); + translateX = textView.getRight() - textWidth - dp(20); } else { - translateX = textView.getLeft() + textWidth + AndroidUtilities.dp(4); + translateX = textView.getLeft() + textWidth + dp(4); } collapsedArrow.setTranslationX(translateX); } @@ -221,47 +323,66 @@ public class CheckBoxCell extends FrameLayout { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); if (currentType == TYPE_CHECK_BOX_UNKNOWN) { - valueTextView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(10), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); - textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(34), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.AT_MOST)); - checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.EXACTLY)); + valueTextView.measure(MeasureSpec.makeMeasureSpec(dp(10), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); + textView.measure(MeasureSpec.makeMeasureSpec(width - dp(34), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.AT_MOST)); + checkBox.measure(MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.EXACTLY)); - setMeasuredDimension(textView.getMeasuredWidth() + AndroidUtilities.dp(29), AndroidUtilities.dp(50)); + setMeasuredDimension(textView.getMeasuredWidth() + dp(29), dp(50)); } else if (isMultiline) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); } else { - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(50) + (needDivider ? 1 : 0)); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), dp(50) + (needDivider ? 1 : 0)); - int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - AndroidUtilities.dp(currentType == TYPE_CHECK_BOX_ROUND ? 60 : 34); + int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - dp(isCheckboxRound() ? 60 : 34); + if (textAnimated) { + availableWidth += (int) animatedTextView.getRightPadding(); + } + if (currentType == TYPE_CHECK_BOX_USER) { + availableWidth -= dp(34); + } if (valueTextView.getLayoutParams() instanceof MarginLayoutParams) { availableWidth -= ((MarginLayoutParams) valueTextView.getLayoutParams()).rightMargin; } + int takenSpace = 0; valueTextView.measure(MeasureSpec.makeMeasureSpec(availableWidth / 2, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); - if (textView.getLayoutParams().width == LayoutHelper.MATCH_PARENT) { - textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - valueTextView.getMeasuredWidth() - AndroidUtilities.dp(8), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); - } else { - textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - valueTextView.getMeasuredWidth() - AndroidUtilities.dp(8), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + takenSpace += valueTextView.getMeasuredWidth(); + if (collapseButton != null) { + collapseButton.measure(MeasureSpec.makeMeasureSpec(availableWidth / 2, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); + takenSpace += collapseButton.getMeasuredWidth() - dp(11); } - checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.EXACTLY)); + if (textView.getLayoutParams().width == LayoutHelper.MATCH_PARENT) { + textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - takenSpace - dp(8), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + } else { + textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - takenSpace - dp(8), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + } + if (avatarImageView != null) { + avatarImageView.measure(MeasureSpec.makeMeasureSpec(dp(34), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(34), MeasureSpec.EXACTLY)); + } + checkBox.measure(MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.EXACTLY)); } if (click1Container != null) { MarginLayoutParams margin = (MarginLayoutParams) click1Container.getLayoutParams(); - click1Container.measure(MeasureSpec.makeMeasureSpec(width - margin.leftMargin - margin.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); + click1Container.measure(MeasureSpec.makeMeasureSpec(width - margin.leftMargin - margin.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); } if (click2Container != null) { - click2Container.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); + click2Container.measure(MeasureSpec.makeMeasureSpec(dp(56), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); } if (collapsedArrow != null) { collapsedArrow.measure( - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(16), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(16), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(dp(16), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(16), MeasureSpec.EXACTLY) ); } } public void setTextColor(int color) { - textView.setTextColor(color); + if (textAnimated) { + animatedTextView.setTextColor(color); + } else { + linksTextView.setTextColor(color); + } } public void setText(CharSequence text, String value, boolean checked, boolean divider) { @@ -269,7 +390,12 @@ public class CheckBoxCell extends FrameLayout { } public void setText(CharSequence text, String value, boolean checked, boolean divider, boolean animated) { - textView.setText(text); + if (textAnimated) { + text = Emoji.replaceEmoji(text, animatedTextView.getPaint().getFontMetricsInt(), false); + animatedTextView.setText(text, animated); + } else { + linksTextView.setText(text); + } if (checkBoxRound != null) { checkBoxRound.setChecked(checked, animated); } else { @@ -280,12 +406,35 @@ public class CheckBoxCell extends FrameLayout { setWillNotDraw(!divider); } + public void setUserOrChat(TLObject userOrChat) { + avatarDrawable.setInfo(userOrChat); + avatarImageView.setForUserOrChat(userOrChat, avatarDrawable); + CharSequence name; + if (userOrChat instanceof TLRPC.User) { + name = UserObject.getUserName((TLRPC.User) userOrChat); + } else { + name = ContactsController.formatName(userOrChat); + } + if (userOrChat instanceof TLRPC.User && ((TLRPC.User) userOrChat).id == MessagesController.getInstance(UserConfig.selectedAccount).telegramAntispamUserId) { + name = LocaleController.getString(R.string.ChannelAntiSpamUser); + } + if (textAnimated) { + name = Emoji.replaceEmoji(name, animatedTextView.getPaint().getFontMetricsInt(), false); + animatedTextView.setText(name); + } else { + linksTextView.setText(name); + } + } + public void setPad(int pad) { - int offset = AndroidUtilities.dp(pad * 40 * (LocaleController.isRTL ? -1 : 1)); + int offset = dp(pad * 40 * (LocaleController.isRTL ? -1 : 1)); if (checkBox != null) { checkBox.setTranslationX(offset); } textView.setTranslationX(offset); + if (avatarImageView != null) { + avatarImageView.setTranslationX(offset); + } if (click1Container != null) { click1Container.setTranslationX(offset); } @@ -299,30 +448,33 @@ public class CheckBoxCell extends FrameLayout { } public void setMultiline(boolean value) { + if (textAnimated) { + return; + } isMultiline = value; LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); LayoutParams layoutParams1 = (LayoutParams) checkBox.getLayoutParams(); if (isMultiline) { - textView.setLines(0); - textView.setMaxLines(0); - textView.setSingleLine(false); - textView.setEllipsize(null); + linksTextView.setLines(0); + linksTextView.setMaxLines(0); + linksTextView.setSingleLine(false); + linksTextView.setEllipsize(null); if (currentType != TYPE_CHECK_BOX_URL) { layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP; - layoutParams.topMargin = AndroidUtilities.dp(14); - layoutParams.bottomMargin = AndroidUtilities.dp(10); + layoutParams.topMargin = dp(14); + layoutParams.bottomMargin = dp(10); } } else { - textView.setLines(1); - textView.setMaxLines(1); - textView.setSingleLine(true); - textView.setEllipsize(TextUtils.TruncateAt.END); + linksTextView.setLines(1); + linksTextView.setMaxLines(1); + linksTextView.setSingleLine(true); + linksTextView.setEllipsize(TextUtils.TruncateAt.END); textView.setPadding(0, 0, 0, 0); layoutParams.height = LayoutParams.MATCH_PARENT; layoutParams.topMargin = 0; - layoutParams1.topMargin = AndroidUtilities.dp(15); + layoutParams1.topMargin = dp(15); } textView.setLayoutParams(layoutParams); checkBox.setLayoutParams(layoutParams1); @@ -353,7 +505,11 @@ public class CheckBoxCell extends FrameLayout { } public TextView getTextView() { - return textView; + return linksTextView; + } + + public AnimatedTextView getAnimatedTextView() { + return animatedTextView; } public TextView getValueTextView() { @@ -383,7 +539,10 @@ public class CheckBoxCell extends FrameLayout { @Override protected void onDraw(Canvas canvas) { if (needDivider) { - int offset = AndroidUtilities.dp(currentType == TYPE_CHECK_BOX_ROUND ? 60 : 20) + (int) Math.abs(textView.getTranslationX()); + int offset = dp(isCheckboxRound() ? 60 : 20) + (int) Math.abs(textView.getTranslationX()); + if (currentType == TYPE_CHECK_BOX_USER) { + offset += dp(39); + } canvas.drawLine(LocaleController.isRTL ? 0 : offset, getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? offset : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } @@ -407,4 +566,74 @@ public class CheckBoxCell extends FrameLayout { public boolean hasIcon() { return checkBoxRound.hasIcon(); } + + public void setCollapseButton(boolean collapsed, CharSequence text, View.OnClickListener onClick) { + if (collapseButton != null) { + collapseButton.set(collapsed, text); + if (onClick != null) { + collapseButton.setOnClickListener(onClick); + } + } + } + + public class CollapseButton extends LinearLayout { + + @Nullable + private ImageView iconView; + private final AnimatedTextView textView; + private final View collapsedArrow; + + @SuppressLint("UseCompatLoadingForDrawables") + public CollapseButton(@NonNull Context context, int iconResId) { + super(context); + + final int color = getThemedColor(Theme.key_windowBackgroundWhiteBlackText); + + if (iconResId != 0) { + iconView = new ImageView(context); + iconView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + iconView.setImageResource(iconResId); + } + + textView = new AnimatedTextView(context, false, true, false); + textView.setTextSize(dp(13)); + textView.setTextColor(color); + textView.setIncludeFontPadding(false); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + + collapsedArrow = new View(context); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.arrow_more).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + collapsedArrow.setBackground(drawable); + + if (LocaleController.isRTL) { + addView(collapsedArrow, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 11, 0, 3, 0)); + addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 16, Gravity.CENTER_VERTICAL, 0, 0, iconView == null ? 11 : 3, 0)); + if (iconView != null) { + addView(iconView, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 0, 0, 11, 0)); + } + } else { + if (iconView != null) { + addView(iconView, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 11, 0, 3, 0)); + } + addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 16, Gravity.CENTER_VERTICAL, iconView == null ? 11 : 0, 0, 3, 0)); + addView(collapsedArrow, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 0, 0, 11, 0)); + } + + setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_listSelector), 16, 16)); + setClickable(true); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp(32), MeasureSpec.EXACTLY)); + } + + public void set(boolean collapsed, CharSequence text) { + textView.cancelAnimation(); + textView.setText(text); + collapsedArrow.animate().cancel(); + collapsedArrow.animate().rotation(collapsed ? 0 : 180).setDuration(340).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java new file mode 100644 index 000000000..a0b23d26d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java @@ -0,0 +1,76 @@ +package org.telegram.ui.Cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class CollapseTextCell extends FrameLayout { + + public final AnimatedTextView textView; + private View collapsedArrow; + private Theme.ResourcesProvider resourcesProvider; + + @SuppressLint("UseCompatLoadingForDrawables") + public CollapseTextCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + textView = new AnimatedTextView(context); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + textView.setTextSize(dp(14)); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); + textView.setOnWidthUpdatedListener(this::updateCollapseArrowTranslation); + addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 21, 0, 38, 3)); + + collapsedArrow = new View(context); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.arrow_more).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider), PorterDuff.Mode.MULTIPLY)); + collapsedArrow.setBackground(drawable); + addView(collapsedArrow, LayoutHelper.createFrameRelatively(14, 14, Gravity.START | Gravity.CENTER_VERTICAL, 21, 1, 0, 3)); + } + + public void set(CharSequence text, boolean collapsed) { + textView.setText(text); + collapsedArrow.animate().cancel(); + collapsedArrow.animate().rotation(collapsed ? 0 : 180).setDuration(340).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } + + public void setColor(int colorKey) { + int color = Theme.getColor(colorKey, resourcesProvider); + textView.setTextColor(color); + collapsedArrow.getBackground().setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(46), MeasureSpec.EXACTLY)); + updateCollapseArrowTranslation(); + } + + private void updateCollapseArrowTranslation() { + float textWidth = textView.getDrawable().getCurrentWidth(); + + float translateX = textWidth + dp(1); + if (LocaleController.isRTL) { + collapsedArrow.setTranslationX(-translateX); + } else { + collapsedArrow.setTranslationX(translateX); + } + } +} 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 aa72bbd80..d8b88d359 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -1619,7 +1619,14 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava messageString = LocaleController.getString("BoostingGiveawayResults", R.string.BoostingGiveawayResults); } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; - messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; + if (mediaPoll.poll.question != null && mediaPoll.poll.question.entities != null) { + SpannableStringBuilder questionText = new SpannableStringBuilder(mediaPoll.poll.question.text); + MediaDataController.addTextStyleRuns(mediaPoll.poll.question.entities, mediaPoll.poll.question.text, questionText); + MediaDataController.addAnimatedEmojiSpans(mediaPoll.poll.question.entities, questionText, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt()); + messageString = new SpannableStringBuilder("\uD83D\uDCCA ").append(questionText); + } else { + messageString = "\uD83D\uDCCA " + mediaPoll.poll.question.text; + } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { @@ -5064,14 +5071,28 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } } else if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; - String innerMessage; + CharSequence innerMessage; int colorKey = Theme.key_chats_attachMessage; if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; if (Build.VERSION.SDK_INT >= 18) { - innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question); + if (mediaPoll.poll.question != null && mediaPoll.poll.question.entities != null) { + SpannableStringBuilder questionText = new SpannableStringBuilder(mediaPoll.poll.question.text.replace('\n', ' ')); + MediaDataController.addTextStyleRuns(mediaPoll.poll.question.entities, mediaPoll.poll.question.text, questionText); + MediaDataController.addAnimatedEmojiSpans(mediaPoll.poll.question.entities, questionText, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt()); + innerMessage = new SpannableStringBuilder("\uD83D\uDCCA \u2068").append(questionText).append("\u2069"); + } else { + innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question.text); + } } else { - innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question); + if (mediaPoll.poll.question != null && mediaPoll.poll.question.entities != null) { + SpannableStringBuilder questionText = new SpannableStringBuilder(mediaPoll.poll.question.text.replace('\n', ' ')); + MediaDataController.addTextStyleRuns(mediaPoll.poll.question.entities, mediaPoll.poll.question.text, questionText); + MediaDataController.addAnimatedEmojiSpans(mediaPoll.poll.question.entities, questionText, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt()); + innerMessage = new SpannableStringBuilder("\uD83D\uDCCA ").append(questionText); + } else { + innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question.text); + } } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { @@ -5098,7 +5119,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava innerMessage = msgText.toString(); colorKey = Theme.key_chats_actionMessage; } - innerMessage = innerMessage.replace('\n', ' '); + if (innerMessage instanceof String) { + innerMessage = ((String) innerMessage).replace('\n', ' '); + } CharSequence message = innerMessage; if (applyThumbs) { message = applyThumbs(innerMessage); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java index f30960e3e..b02dc7dea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java @@ -148,8 +148,8 @@ public class EditTextCell extends FrameLayout { } editText.setPadding(dp(21), dp(15), dp((maxLength > 0 ? 42 : 0) + 21), dp(15)); editText.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | (multiline ? InputType.TYPE_TEXT_FLAG_MULTI_LINE : 0) | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); - editText.setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | (multiline ? InputType.TYPE_TEXT_FLAG_MULTI_LINE : 0) | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + editText.setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); editText.setHint(hint); editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); editText.setCursorSize(dp(19)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java index 7544e76c7..872de319b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java @@ -98,7 +98,7 @@ public class GraySectionCell extends FrameLayout { rightTextView.setOnClickListener(null); } - public void setText(String left, String right, OnClickListener onClickListener) { + public void setText(CharSequence left, CharSequence right, OnClickListener onClickListener) { textView.setText(left); rightTextView.setText(right, false); rightTextView.setOnClickListener(onClickListener); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java index 009fd0257..e1449f526 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -26,19 +26,24 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.LayoutHelper; import java.util.ArrayList; public class HeaderCell extends FrameLayout { + public int id; + protected int padding; protected int bottomMargin; private TextView textView; + private AnimatedTextView animatedTextView; private SimpleTextView textView2; private int height = 40; private final Theme.ResourcesProvider resourcesProvider; + private boolean animated; public HeaderCell(Context context) { this(context, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, false, null); @@ -65,20 +70,36 @@ public class HeaderCell extends FrameLayout { } public HeaderCell(Context context, int textColorKey, int padding, int topMargin, int bottomMargin, boolean text2, Theme.ResourcesProvider resourcesProvider) { + this(context, textColorKey, padding, topMargin, bottomMargin, text2, false, resourcesProvider); + } + + public HeaderCell(Context context, int textColorKey, int padding, int topMargin, int bottomMargin, boolean text2, boolean animated, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.padding = padding; this.bottomMargin = bottomMargin; + this.animated = animated; - textView = new TextView(getContext()); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - textView.setEllipsize(TextUtils.TruncateAt.END); - textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setMinHeight(AndroidUtilities.dp(height - topMargin)); - textView.setTextColor(getThemedColor(textColorKey)); - textView.setTag(textColorKey); - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); + if (animated) { + animatedTextView = new AnimatedTextView(getContext()); + animatedTextView.setTextSize(AndroidUtilities.dp(15)); + animatedTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + animatedTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + animatedTextView.setTextColor(getThemedColor(textColorKey)); + animatedTextView.setTag(textColorKey); + animatedTextView.getDrawable().setHacks(true, true, false); + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, height - topMargin, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); + } else { + textView = new TextView(getContext()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setMinHeight(AndroidUtilities.dp(height - topMargin)); + textView.setTextColor(getThemedColor(textColorKey)); + textView.setTag(textColorKey); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); + } if (text2) { textView2 = new SimpleTextView(getContext()); @@ -120,7 +141,11 @@ public class HeaderCell extends FrameLayout { } public void setTextSize(float dip) { - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dip); + if (animated) { + animatedTextView.setTextSize(AndroidUtilities.dp(dip)); + } else { + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dip); + } } public void setTextColor(int color) { @@ -128,8 +153,17 @@ public class HeaderCell extends FrameLayout { } public void setText(CharSequence text) { - textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setText(text); + setText(text, false); + } + + public void setText(CharSequence text, boolean animate) { + if (this.animated) { + animatedTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + animatedTextView.setText(text, animate); + } else { + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setText(text); + } } public void setText2(CharSequence text) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java index 4de632428..26f44a017 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java @@ -8,6 +8,8 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -15,6 +17,7 @@ import android.graphics.PorterDuffColorFilter; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; @@ -25,13 +28,16 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Switch; public class NotificationsCheckCell extends FrameLayout { private TextView textView; - private TextView valueTextView; + private AnimatedTextView valueTextView; + private TextView multilineValueTextView; @SuppressWarnings("FieldCanBeLocal") private ImageView imageView; private Switch checkBox; @@ -78,16 +84,26 @@ public class NotificationsCheckCell extends FrameLayout { textView.setEllipsize(TextUtils.TruncateAt.END); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 13 + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); - valueTextView = new TextView(context); + valueTextView = new AnimatedTextView(context); + valueTextView.setAnimationProperties(.55f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); - valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + valueTextView.setTextSize(dp(13)); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - valueTextView.setLines(1); - valueTextView.setMaxLines(1); - valueTextView.setSingleLine(true); valueTextView.setPadding(0, 0, 0, 0); - valueTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 38 - (withImage ? 2 : 0) + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); + valueTextView.setEllipsizeByGradient(true); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 38 - 9 - (withImage ? 2 : 0) + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); + + multilineValueTextView = new TextView(context); + multilineValueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); + multilineValueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + multilineValueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + multilineValueTextView.setLines(0); + multilineValueTextView.setMaxLines(0); + multilineValueTextView.setSingleLine(false); + multilineValueTextView.setEllipsize(null); + multilineValueTextView.setPadding(0, 0, 0, 0); + multilineValueTextView.setVisibility(View.GONE); + addView(multilineValueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 38 - (withImage ? 2 : 0) + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); checkBox = new Switch(context, resourcesProvider) { @Override @@ -113,7 +129,7 @@ public class NotificationsCheckCell extends FrameLayout { if (isMultiline) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); } else { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(currentHeight), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(currentHeight), MeasureSpec.EXACTLY)); } } @@ -130,38 +146,46 @@ public class NotificationsCheckCell extends FrameLayout { } public void setTextAndValueAndIconAndCheck(CharSequence text, CharSequence value, int iconResId, boolean checked, int iconType, boolean multiline, boolean divider) { + setTextAndValueAndIconAndCheck(text, value, iconResId, checked, iconType, multiline, divider, false); + } + + public void setTextAndValueAndIconAndCheck(CharSequence text, CharSequence value, int iconResId, boolean checked, int iconType, boolean multiline, boolean divider, boolean animated) { textView.setText(text); - valueTextView.setText(value); if (imageView != null) { imageView.setImageResource(iconResId); imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogIcon), PorterDuff.Mode.MULTIPLY)); } checkBox.setChecked(checked, iconType, animationsEnabled); - valueTextView.setVisibility(VISIBLE); - needDivider = divider; setMultiline(multiline); + if (isMultiline) { + multilineValueTextView.setText(value); + } else { + valueTextView.setText(value, animated); + } + (isMultiline ? multilineValueTextView : valueTextView).setVisibility(VISIBLE); checkBox.setContentDescription(text); + needDivider = divider; } public void setMultiline(boolean multiline) { isMultiline = multiline; if (multiline) { - valueTextView.setLines(0); - valueTextView.setMaxLines(0); - valueTextView.setSingleLine(false); - valueTextView.setEllipsize(null); - valueTextView.setPadding(0, 0, 0, AndroidUtilities.dp(14)); + multilineValueTextView.setVisibility(View.VISIBLE); + valueTextView.setVisibility(View.GONE); + multilineValueTextView.setPadding(0, 0, 0, dp(14)); } else { - valueTextView.setLines(1); - valueTextView.setMaxLines(1); - valueTextView.setSingleLine(true); - valueTextView.setEllipsize(TextUtils.TruncateAt.END); + multilineValueTextView.setVisibility(View.GONE); + valueTextView.setVisibility(View.VISIBLE); valueTextView.setPadding(0, 0, 0, 0); } } public void setValue(CharSequence value) { - valueTextView.setText(value); + if (isMultiline) { + multilineValueTextView.setText(value); + } else { + valueTextView.setText(value, true); + } } public void setDrawLine(boolean value) { @@ -184,17 +208,17 @@ public class NotificationsCheckCell extends FrameLayout { protected void onDraw(Canvas canvas) { if (needDivider) { canvas.drawLine( - LocaleController.isRTL ? 0 : AndroidUtilities.dp(imageView != null ? 64 : 20), + LocaleController.isRTL ? 0 : dp(imageView != null ? 64 : 20), getMeasuredHeight() - 1, - getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(imageView != null ? 64 : 20) : 0), + getMeasuredWidth() - (LocaleController.isRTL ? dp(imageView != null ? 64 : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint ); } if (drawLine) { - int x = LocaleController.isRTL ? AndroidUtilities.dp(76) : getMeasuredWidth() - AndroidUtilities.dp(76) - 1; - int y = (getMeasuredHeight() - AndroidUtilities.dp(22)) / 2; - canvas.drawRect(x, y, x + 2, y + AndroidUtilities.dp(22), Theme.dividerPaint); + int x = LocaleController.isRTL ? dp(76) : getMeasuredWidth() - dp(76) - 1; + int y = (getMeasuredHeight() - dp(22)) / 2; + canvas.drawRect(x, y, x + 2, y + dp(22), Theme.dividerPaint); } } @@ -208,9 +232,16 @@ public class NotificationsCheckCell extends FrameLayout { info.setClassName("android.widget.Switch"); StringBuilder sb = new StringBuilder(); sb.append(textView.getText()); - if (valueTextView != null && !TextUtils.isEmpty(valueTextView.getText())) { - sb.append("\n"); - sb.append(valueTextView.getText()); + if (isMultiline) { + if (multilineValueTextView != null && !TextUtils.isEmpty(multilineValueTextView.getText())) { + sb.append("\n"); + sb.append(multilineValueTextView.getText()); + } + } else { + if (valueTextView != null && !TextUtils.isEmpty(valueTextView.getText())) { + sb.append("\n"); + sb.append(valueTextView.getText()); + } } info.setContentDescription(sb); info.setCheckable(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java index 93c17c673..40a3e4c5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java @@ -13,6 +13,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; +import android.content.ContentUris; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -23,10 +24,12 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.text.TextUtils; +import android.util.Size; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -44,6 +47,7 @@ import androidx.core.math.MathUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; @@ -60,6 +64,8 @@ import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.Components.spoilers.SpoilerEffect2; import org.telegram.ui.PhotoViewer; +import java.io.IOException; + public class PhotoAttachPhotoCell extends FrameLayout { private BackupImageView imageView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java index 2c710370f..e041bf7c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java @@ -8,13 +8,19 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.os.Build; +import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.TypedValue; @@ -27,19 +33,28 @@ import android.view.inputmethod.InputConnection; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.ChatActivityEnterViewAnimatedIconView; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EditTextCaption; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.SuggestEmojiView; import java.util.ArrayList; -public class PollEditTextCell extends FrameLayout { +public class PollEditTextCell extends FrameLayout implements SuggestEmojiView.AnchorViewDelegate { + + public static final int TYPE_DEFAULT = 0; + public static final int TYPE_EMOJI = 1; private EditTextBoldCursor textView; private ImageView deleteImageView; @@ -50,89 +65,79 @@ public class PollEditTextCell extends FrameLayout { private boolean needDivider; private AnimatorSet checkBoxAnimation; private boolean alwaysShowText2; + private ChatActivityEnterViewAnimatedIconView emojiButton; + private ValueAnimator valueAnimator; public PollEditTextCell(Context context, OnClickListener onDelete) { - this(context, false, onDelete); + this(context, false, TYPE_DEFAULT, onDelete); } - public PollEditTextCell(Context context, boolean caption, OnClickListener onDelete) { + public PollEditTextCell(Context context, boolean caption, int type, OnClickListener onDelete) { super(context); - if (caption) { - textView = new EditTextCaption(context, null) { - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - InputConnection conn = super.onCreateInputConnection(outAttrs); - if (showNextButton) { - outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; - } - return conn; - } + textView = new EditTextCaption(context, null) { + @Override + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + } - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - onEditTextDraw(this, canvas); + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + InputConnection conn = super.onCreateInputConnection(outAttrs); + if (showNextButton) { + outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; } + return conn; + } - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled()) { - return false; - } - if (event.getAction() == MotionEvent.ACTION_UP) { - onFieldTouchUp(this); - } - return super.onTouchEvent(event); - } + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + onEditTextDraw(this, canvas); + } - @Override - public ActionMode startActionMode(ActionMode.Callback callback, int type) { - ActionMode actionMode = super.startActionMode(callback, type); - onActionModeStart(this, actionMode); - return actionMode; + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; } + if (event.getAction() == MotionEvent.ACTION_UP) { + onFieldTouchUp(this); + } + return super.onTouchEvent(event); + } - @Override - public ActionMode startActionMode(ActionMode.Callback callback) { - ActionMode actionMode = super.startActionMode(callback); - onActionModeStart(this, actionMode); - return actionMode; - } - }; - ((EditTextCaption) textView).setAllowTextEntitiesIntersection(true); - } else { - textView = new EditTextBoldCursor(context) { - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - InputConnection conn = super.onCreateInputConnection(outAttrs); - if (showNextButton) { - outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + if (type == TYPE_EMOJI) { + if (focused && emojiButton.getVisibility() == View.GONE) { + setEmojiButtonVisibility(true); + } else if (!focused && emojiButton.getVisibility() == View.VISIBLE) { + setEmojiButtonVisibility(false); } - return conn; } + } - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - onEditTextDraw(this, canvas); - } + @Override + public ActionMode startActionMode(ActionMode.Callback callback, int type) { + ActionMode actionMode = super.startActionMode(callback, type); + onActionModeStart(this, actionMode); + return actionMode; + } - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled()) { - return false; - } - if (event.getAction() == MotionEvent.ACTION_UP) { - onFieldTouchUp(this); - } - return super.onTouchEvent(event); - } - }; - } + @Override + public ActionMode startActionMode(ActionMode.Callback callback) { + ActionMode actionMode = super.startActionMode(callback); + onActionModeStart(this, actionMode); + return actionMode; + } + }; + ((EditTextCaption) textView).setAllowTextEntitiesIntersection(true); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); textView.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setMaxLines(type == TYPE_EMOJI ? 4 : Integer.MAX_VALUE); // textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setBackgroundDrawable(null); textView.setImeOptions(textView.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI); @@ -140,7 +145,8 @@ public class PollEditTextCell extends FrameLayout { textView.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(10), AndroidUtilities.dp(4), AndroidUtilities.dp(11)); if (onDelete != null) { - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 58 : 64, 0, !LocaleController.isRTL ? 58 : 64, 0)); + int endMargin = type == TYPE_EMOJI ? 102: 58; + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? endMargin : 64, 0, !LocaleController.isRTL ? endMargin : 64, 0)); moveImageView = new ImageView(context); moveImageView.setFocusable(false); @@ -179,7 +185,27 @@ public class PollEditTextCell extends FrameLayout { onCheckBoxClick(PollEditTextCell.this, !checkBox.isChecked()); }); } else { - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 19, 0, 19, 0)); + int endMargin = type == TYPE_EMOJI ? 80: 19; + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? endMargin : 19, 0, LocaleController.isRTL ? 19 : endMargin, 0)); + } + + if (type == TYPE_EMOJI) { + emojiButton = new ChatActivityEnterViewAnimatedIconView(context); + emojiButton.setAlpha(0.80f); + emojiButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + int padding = dp(9.5f); + emojiButton.setPadding(padding, padding, padding, padding); + emojiButton.setVisibility(View.GONE); + int endMargin = deleteImageView == null ? 3 : 48; + addView(emojiButton, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), LocaleController.isRTL ? endMargin : 0, 0, LocaleController.isRTL ? 0 : endMargin, 0)); + if (Build.VERSION.SDK_INT >= 21) { + emojiButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector))); + } + emojiButton.setOnClickListener(view -> { + onEmojiButtonClicked(this); + }); + emojiButton.setContentDescription(LocaleController.getString("Emoji", R.string.Emoji)); } } @@ -197,6 +223,9 @@ public class PollEditTextCell extends FrameLayout { if (deleteImageView != null) { deleteImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); } + if (emojiButton != null) { + emojiButton.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); + } if (moveImageView != null) { moveImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); } @@ -212,7 +241,11 @@ public class PollEditTextCell extends FrameLayout { } else if (deleteImageView == null) { right = 70; } else { - right = 122; + if (emojiButton != null) { + right = 174; + } else { + right = 122; + } } textView.measure(MeasureSpec.makeMeasureSpec(width - getPaddingLeft() - getPaddingRight() - AndroidUtilities.dp(right), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = textView.getMeasuredHeight(); @@ -335,6 +368,10 @@ public class PollEditTextCell extends FrameLayout { setWillNotDraw(!divider); } + public ChatActivityEnterViewAnimatedIconView getEmojiButton() { + return emojiButton; + } + public void setEnabled(boolean value, ArrayList animators) { setEnabled(value); } @@ -343,6 +380,10 @@ public class PollEditTextCell extends FrameLayout { } + protected void onEmojiButtonClicked(PollEditTextCell cell) { + + } + public void setText2(String text) { if (textView2 == null) { return; @@ -354,10 +395,94 @@ public class PollEditTextCell extends FrameLayout { return textView2; } + private void setEmojiButtonVisibility(boolean visible) { + if (valueAnimator != null) { + valueAnimator.cancel(); + } + if (visible) { + emojiButton.setVisibility(View.VISIBLE); + emojiButton.setScaleX(0f); + emojiButton.setScaleY(0f); + emojiButton.setAlpha(0f); + } + valueAnimator = ValueAnimator.ofFloat(visible ? 0 : 1, visible ? 1 : 0); + valueAnimator.addUpdateListener(animation -> { + float value = (Float) animation.getAnimatedValue(); + emojiButton.setScaleX(value); + emojiButton.setScaleY(value); + emojiButton.setAlpha(Math.max(value, 0.80f)); + if (textView2 != null && deleteImageView == null && textView2.getVisibility() == View.VISIBLE) { + textView2.setTranslationY(AndroidUtilities.dp(26) * value); + } + }); + valueAnimator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(@NonNull Animator animation) { + + } + + @Override + public void onAnimationEnd(@NonNull Animator animation) { + if (!visible) { + emojiButton.setVisibility(View.GONE); + } else { + emojiButton.setScaleX(1f); + emojiButton.setScaleY(1f); + emojiButton.setAlpha(0.80f); + } + } + + @Override + public void onAnimationCancel(@NonNull Animator animation) { + + } + + @Override + public void onAnimationRepeat(@NonNull Animator animation) { + + } + }); + valueAnimator.setDuration(200L); + valueAnimator.start(); + } + @Override protected void onDraw(Canvas canvas) { if (needDivider && drawDivider()) { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(moveImageView != null ? 63 : 20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(moveImageView != null ? 63 : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public BaseFragment getParentFragment() { + return null; + } + + @Override + public void setFieldText(CharSequence text) { + textView.setText(text); + } + + @Override + public void addTextChangedListener(TextWatcher watcher) { + textView.addTextChangedListener(watcher); + } + + @Override + public EditTextBoldCursor getEditField() { + return textView; + } + + @Override + public CharSequence getFieldText() { + if (textView.length() > 0) { + return textView.getText(); + } + return null; + } + + @Override + public Editable getEditText() { + return textView.getText(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java index 6ebf57b6c..937a4a496 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java @@ -25,6 +25,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; @@ -53,7 +54,7 @@ public class ProfileChannelCell extends FrameLayout { private final TextView headerView; private final AnimatedTextView subscribersView; - private final DialogCell dialogCell; + public final DialogCell dialogCell; public ProfileChannelCell(BaseFragment fragment) { super(fragment.getContext()); @@ -67,7 +68,7 @@ public class ProfileChannelCell extends FrameLayout { headerView = new TextView(context); headerView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); headerView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - headerView.setText("Channel"); + headerView.setText(LocaleController.getString(R.string.ProfileChannel)); headerLayout.addView(headerView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); subscribersView = new ClickableAnimatedTextView(context); @@ -80,6 +81,7 @@ public class ProfileChannelCell extends FrameLayout { headerLayout.addView(subscribersView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 17, Gravity.LEFT | Gravity.TOP, 4, 2, 4, 0)); dialogCell = new DialogCell(null, context, false, true, UserConfig.selectedAccount, resourcesProvider); + dialogCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); dialogCell.setDialogCellDelegate(new DialogCell.DialogCellDelegate() { @Override public void onButtonClicked(DialogCell dialogCell) { @@ -149,8 +151,8 @@ public class ProfileChannelCell extends FrameLayout { private final LoadingDrawable loadingDrawable; @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); float loading = loadingAlpha.set(this.loading); if (loading > 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java index 5315eb88c..508f6c04d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java @@ -29,6 +29,8 @@ public class RadioColorCell extends FrameLayout { private RadioButton radioButton; private final Theme.ResourcesProvider resourcesProvider; + public int heightDp = 50; + public RadioColorCell(Context context) { this(context, null); } @@ -69,7 +71,7 @@ public class RadioColorCell extends FrameLayout { } super.onMeasure( MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (text2View.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(4) + text2View.getMeasuredHeight() : 0), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(heightDp) + (text2View.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(4) + text2View.getMeasuredHeight() : 0), MeasureSpec.EXACTLY) ); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java index f8cfed7e3..92cebb05c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java @@ -185,7 +185,7 @@ public class ReactedUserHolderView extends FrameLayout { dialogId = user.id; titleView.setText(UserObject.getUserName(user)); } else { - dialogId = chat.id; + dialogId = -chat.id; titleView.setText(chat.title); } 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 60a9f99e6..08ceb69bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java @@ -8,16 +8,23 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.view.Gravity; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; + +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocationController; @@ -25,7 +32,10 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.Components.ShareLocationDrawable; @@ -39,7 +49,9 @@ public class SendLocationCell extends FrameLayout { private long dialogId; private RectF rect; private boolean live; + private boolean liveDisable; private final Theme.ResourcesProvider resourcesProvider; + public boolean useDivider; private Runnable invalidateRunnable = new Runnable() { @Override @@ -50,49 +62,56 @@ public class SendLocationCell extends FrameLayout { } }; - public SendLocationCell(Context context, boolean live, Theme.ResourcesProvider resourcesProvider) { + public SendLocationCell(Context context, boolean live, boolean liveDisable, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.live = live; + this.liveDisable = liveDisable; imageView = new ImageView(context); - - setBackground(Theme.AdaptiveRipple.rect()); - - imageView.setTag(live ? Theme.key_location_sendLiveLocationBackground + Theme.key_location_sendLiveLocationIcon : Theme.key_location_sendLocationBackground + Theme.key_location_sendLocationIcon); - Drawable circle = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(live ? Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground), getThemedColor(live ? Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground)); - if (live) { - rect = new RectF(); - Drawable drawable = new ShareLocationDrawable(context, 4); - drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLiveLocationIcon), PorterDuff.Mode.MULTIPLY)); - CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); - combinedDrawable.setCustomSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); - imageView.setBackgroundDrawable(combinedDrawable); - AndroidUtilities.runOnUIThread(invalidateRunnable, 1000); - setWillNotDraw(false); - } else { - Drawable drawable = getResources().getDrawable(R.drawable.pin).mutate(); - drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLocationIcon), PorterDuff.Mode.MULTIPLY)); - CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); - combinedDrawable.setCustomSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); - combinedDrawable.setIconSize(AndroidUtilities.dp(24), AndroidUtilities.dp(24)); - imageView.setBackgroundDrawable(combinedDrawable); - } - addView(imageView, LayoutHelper.createFrame(42, 42, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 15, 12, LocaleController.isRTL ? 15 : 0, 0)); + addView(imageView, LayoutHelper.createFrame(46, 46, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 13, 0, LocaleController.isRTL ? 13 : 0, 0)); titleTextView = new SimpleTextView(context); titleTextView.setTextSize(16); - titleTextView.setTag(live ? Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText); - titleTextView.setTextColor(getThemedColor(live ? Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText)); titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 12, LocaleController.isRTL ? 73 : 16, 0)); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 9.33f, LocaleController.isRTL ? 73 : 16, 0)); accurateTextView = new SimpleTextView(context); accurateTextView.setTextSize(14); accurateTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); accurateTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(accurateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 37, LocaleController.isRTL ? 73 : 16, 0)); + addView(accurateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 33, LocaleController.isRTL ? 73 : 16, 0)); + + updateImage(); + + setWillNotDraw(false); + } + private void updateImage() { + titleTextView.setTag(live ? liveDisable ? Theme.key_text_RedBold : Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText); + titleTextView.setTextColor(getThemedColor(live ? liveDisable ? Theme.key_text_RedBold : Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText)); + + imageView.setTag(live ? liveDisable ? Theme.key_color_red : Theme.key_location_sendLiveLocationBackground + Theme.key_location_sendLiveLocationIcon : Theme.key_location_sendLocationBackground + Theme.key_location_sendLocationIcon); + Drawable circle = Theme.createSimpleSelectorCircleDrawable(dp(46), getThemedColor(live ? liveDisable ? Theme.key_color_red : Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground), getThemedColor(live ? liveDisable ? Theme.key_color_red : Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground)); + if (live) { + rect = new RectF(); + Drawable drawable = new ShareLocationDrawable(getContext(), liveDisable ? ShareLocationDrawable.TYPE_DISABLE : ShareLocationDrawable.TYPE_ADD); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLiveLocationIcon), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); + combinedDrawable.setCustomSize(dp(46), dp(46)); + imageView.setBackgroundDrawable(combinedDrawable); + if (!liveDisable) { + AndroidUtilities.cancelRunOnUIThread(invalidateRunnable); + AndroidUtilities.runOnUIThread(invalidateRunnable, 1000); + } + } else { + Drawable drawable = getResources().getDrawable(R.drawable.pin).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLocationIcon), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); + combinedDrawable.setCustomSize(dp(46), dp(46)); + combinedDrawable.setIconSize(dp(24), dp(24)); + imageView.setBackgroundDrawable(combinedDrawable); + } } private ImageView getImageView() { @@ -113,7 +132,7 @@ public class SendLocationCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(66), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(60), MeasureSpec.EXACTLY)); } @Override @@ -126,6 +145,7 @@ public class SendLocationCell extends FrameLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); if (rect != null) { + AndroidUtilities.cancelRunOnUIThread(invalidateRunnable); AndroidUtilities.runOnUIThread(invalidateRunnable, 1000); } } @@ -145,41 +165,93 @@ public class SendLocationCell extends FrameLayout { private void checkText() { LocationController.SharingLocationInfo info = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); if (info != null) { - setText(LocaleController.getString("StopLiveLocation", R.string.StopLiveLocation), LocaleController.formatLocationUpdateDate(info.messageObject.messageOwner.edit_date != 0 ? info.messageObject.messageOwner.edit_date : info.messageObject.messageOwner.date)); + if (liveDisable) { + setText(LocaleController.getString(R.string.StopLiveLocation), LocaleController.formatLocationUpdateDate(info.messageObject.messageOwner.edit_date != 0 ? info.messageObject.messageOwner.edit_date : info.messageObject.messageOwner.date)); + } else { + setText(LocaleController.getString(R.string.SharingLiveLocation), LocaleController.getString(R.string.SharingLiveLocationAdd)); + } } else { setText(LocaleController.getString("SendLiveLocation", R.string.SendLiveLocation), LocaleController.getString("SendLiveLocationInfo", R.string.SendLiveLocationInfo)); } } + private final AnimatedFloat progress = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat progressAlpha = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat progressScale = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedTextView.AnimatedTextDrawable textDrawable = new AnimatedTextView.AnimatedTextDrawable(false, true, false); + { + textDrawable.setAnimationProperties(.3f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + textDrawable.setTextSize(dp(12)); + textDrawable.setTypeface(Typeface.DEFAULT_BOLD); + textDrawable.setGravity(Gravity.CENTER); + textDrawable.setCallback(this); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == textDrawable || super.verifyDrawable(who); + } + @Override protected void onDraw(Canvas canvas) { - LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); - if (currentInfo == null) { + if (useDivider) { + Paint dividerPaint = Theme.getThemePaint(Theme.key_paint_divider, resourcesProvider); + if (dividerPaint != null) { + canvas.drawRect(LocaleController.isRTL ? 0 : dp(73), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? dp(73) : 0), getMeasuredHeight(), dividerPaint); + } + } + + if (liveDisable) { return; } + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + float progress = this.progress.get(); + + float alpha; int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (currentInfo.stopTime < currentTime) { + if (currentInfo != null && currentInfo.stopTime >= currentTime && currentInfo.period != 0x7FFFFFFF) { + progress = Math.abs(currentInfo.stopTime - currentTime) / (float) currentInfo.period; + alpha = this.progressAlpha.set(true); + } else { + alpha = this.progressAlpha.set(false); + } + + if (alpha <= 0) { return; } - float progress = Math.abs(currentInfo.stopTime - currentTime) / (float) currentInfo.period; if (LocaleController.isRTL) { - rect.set(AndroidUtilities.dp(13), AndroidUtilities.dp(18), AndroidUtilities.dp(43), AndroidUtilities.dp(48)); + rect.set(dp(13), getMeasuredHeight() / 2f - dp(15), dp(43), getMeasuredHeight() / 2f + dp(15)); } else { - rect.set(getMeasuredWidth() - AndroidUtilities.dp(43), AndroidUtilities.dp(18), getMeasuredWidth() - AndroidUtilities.dp(13), AndroidUtilities.dp(48)); + rect.set(getMeasuredWidth() - dp(43), getMeasuredHeight() / 2f - dp(15), getMeasuredWidth() - dp(13), getMeasuredHeight() / 2f + dp(15)); } + canvas.save(); + final float s = AndroidUtilities.lerp(.6f, 1f, alpha); + canvas.scale(s, s, rect.centerX(), rect.centerY()); + int color = getThemedColor(Theme.key_location_liveLocationProgress); Theme.chat_radialProgress2Paint.setColor(color); - Theme.chat_livePaint.setColor(color); - canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); + int a = Theme.chat_radialProgress2Paint.getAlpha(); + Theme.chat_radialProgress2Paint.setAlpha((int) (.20f * a * alpha)); + canvas.drawArc(rect, -90, 360, false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha((int) (a * alpha)); + canvas.drawArc(rect, -90, -360 * this.progress.set(progress), false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha(a); - String text = LocaleController.formatLocationLeftTime(Math.abs(currentInfo.stopTime - currentTime)); + if (currentInfo != null) { + textDrawable.setText(LocaleController.formatLocationLeftTime(Math.abs(currentInfo.stopTime - currentTime))); + } + int len = textDrawable.getText().length(); + final float s2 = progressScale.set(len > 4 ? .75f : (len > 3 ? .85f : 1f)); + canvas.scale(s2, s2, rect.centerX(), rect.centerY()); + textDrawable.setTextColor(color); + textDrawable.setAlpha((int) (0xFF * alpha)); + textDrawable.setBounds((int) rect.left, (int) (rect.centerY() - dp(12 + 1)), (int) rect.right, (int) (rect.centerY() + dp(12))); + textDrawable.draw(canvas); - float size = Theme.chat_livePaint.measureText(text); - - canvas.drawText(text, rect.centerX() - size / 2, AndroidUtilities.dp(37), Theme.chat_livePaint); + canvas.restore(); } private int getThemedColor(int key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java index cfaf78e02..f2875b003 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java @@ -6,6 +6,7 @@ import android.text.Spanned; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -19,12 +20,15 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.URLSpanNoUnderline; public class SettingsSuggestionCell extends LinearLayout { public final static int TYPE_PHONE = 0; public final static int TYPE_PASSWORD = 1; + public final static int TYPE_GRACE = 2; private TextView textView; private TextView detailTextView; @@ -49,22 +53,23 @@ public class SettingsSuggestionCell extends LinearLayout { textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 15, 21, 0)); - detailTextView = new TextView(context); - detailTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); - detailTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + detailTextView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + detailTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + detailTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); detailTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); detailTextView.setHighlightColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection, resourcesProvider)); detailTextView.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy()); detailTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(detailTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 21, 8, 21, 0)); + addView(detailTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 21, 14, 21, 0)); LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(HORIZONTAL); - addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 40, 21, 17, 21, 20)); + addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44, 21, 16, 21, 15)); for (int a = 0; a < 2; a++) { TextView textView = new TextView(context); - textView.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 4)); + textView.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 8)); + ScaleStateListAnimator.apply(textView, 0.02f, 1.5f); textView.setLines(1); textView.setSingleLine(true); textView.setGravity(Gravity.CENTER_HORIZONTAL); @@ -72,8 +77,8 @@ public class SettingsSuggestionCell extends LinearLayout { textView.setGravity(Gravity.CENTER); textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - linearLayout.addView(textView, LayoutHelper.createLinear(0, 40, 0.5f, a == 0 ? 0 : 4, 0, a == 0 ? 4 : 0, 0)); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + linearLayout.addView(textView, LayoutHelper.createLinear(0, 44, 0.5f, a == 0 ? 0 : 4, 0, a == 0 ? 4 : 0, 0)); if (a == 0) { yesButton = textView; yesButton.setOnClickListener(v -> onYesClick(currentType)); @@ -104,12 +109,19 @@ public class SettingsSuggestionCell extends LinearLayout { } detailTextView.setText(builder); yesButton.setText(LocaleController.getString("CheckPhoneNumberYes", R.string.CheckPhoneNumberYes)); + noButton.setVisibility(View.VISIBLE); noButton.setText(LocaleController.getString("CheckPhoneNumberNo", R.string.CheckPhoneNumberNo)); } else if (type == TYPE_PASSWORD) { textView.setText(LocaleController.getString("YourPasswordHeader", R.string.YourPasswordHeader)); detailTextView.setText(LocaleController.getString("YourPasswordRemember", R.string.YourPasswordRemember)); yesButton.setText(LocaleController.getString("YourPasswordRememberYes", R.string.YourPasswordRememberYes)); + noButton.setVisibility(View.VISIBLE); noButton.setText(LocaleController.getString("YourPasswordRememberNo", R.string.YourPasswordRememberNo)); + } else if (type == TYPE_GRACE) { + textView.setText(LocaleController.getString(R.string.GraceSuggestionTitle)); + detailTextView.setText(LocaleController.getString(R.string.GraceSuggestionMessage)); + yesButton.setText(LocaleController.getString(R.string.GraceSuggestionButton)); + noButton.setVisibility(View.GONE); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java index f54eeb602..2ab3062a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java @@ -8,6 +8,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -58,6 +59,9 @@ import org.telegram.ui.Components.spoilers.SpoilerEffect2; import org.telegram.ui.PhotoViewer; import org.telegram.ui.Stories.StoryWidgetsImageDecorator; import org.telegram.ui.Stories.recorder.DominantColors; +import org.telegram.ui.Stories.recorder.StoryPrivacyBottomSheet; + +import java.util.HashMap; public class SharedPhotoVideoCell2 extends FrameLayout { @@ -77,6 +81,10 @@ public class SharedPhotoVideoCell2 extends FrameLayout { String videoText; boolean drawVideoIcon = true; + private int privacyType; + private Bitmap privacyBitmap; + private Paint privacyPaint; + boolean drawViews; AnimatedFloat viewsAlpha = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); AnimatedTextView.AnimatedTextDrawable viewsText = new AnimatedTextView.AnimatedTextDrawable(false, true, true); @@ -93,6 +101,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout { private boolean gradientDrawableLoading; public boolean isStory; + public boolean isStoryPinned; static long lastUpdateDownloadSettingsTime; static boolean lastAutoDownload; @@ -169,7 +178,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout { if (currentMessageObject == null && messageObject == null) { return; } - if (currentMessageObject != null && messageObject != null && currentMessageObject.getId() == messageObject.getId() && oldParentColumsCount == parentColumnsCount) { + if (currentMessageObject != null && messageObject != null && currentMessageObject.getId() == messageObject.getId() && oldParentColumsCount == parentColumnsCount && (privacyType == 100) == isStoryPinned) { return; } currentMessageObject = messageObject; @@ -186,6 +195,8 @@ public class SharedPhotoVideoCell2 extends FrameLayout { showVideoLayout = false; gradientDrawableLoading = false; gradientDrawable = null; + privacyType = -1; + privacyBitmap = null; return; } else { if (attached) { @@ -303,6 +314,35 @@ public class SharedPhotoVideoCell2 extends FrameLayout { imageReceiver.addDecorator(new StoryWidgetsImageDecorator(messageObject.storyItem)); } + if (isStoryPinned) { + setPrivacyType(100, R.drawable.msg_pin_mini); + } else if (isStory && messageObject.storyItem != null) { + if (messageObject.storyItem.parsedPrivacy == null) { + messageObject.storyItem.parsedPrivacy = new StoryPrivacyBottomSheet.StoryPrivacy(currentAccount, messageObject.storyItem.privacy); + } + if (messageObject.storyItem.parsedPrivacy.type == StoryPrivacyBottomSheet.TYPE_CONTACTS) { + setPrivacyType(messageObject.storyItem.parsedPrivacy.type, R.drawable.msg_folders_private); + } else if (messageObject.storyItem.parsedPrivacy.type == StoryPrivacyBottomSheet.TYPE_CLOSE_FRIENDS) { + setPrivacyType(messageObject.storyItem.parsedPrivacy.type, R.drawable.msg_stories_closefriends); + } else if (messageObject.storyItem.parsedPrivacy.type == StoryPrivacyBottomSheet.TYPE_SELECTED_CONTACTS) { + setPrivacyType(messageObject.storyItem.parsedPrivacy.type, R.drawable.msg_folders_groups); + } else { + setPrivacyType(-1, 0); + } + } else { + setPrivacyType(-1, 0); + } + + invalidate(); + } + + private void setPrivacyType(int type, int resId) { + if (privacyType == type) return; + privacyType = type; + privacyBitmap = null; + if (resId != 0) { + privacyBitmap = sharedResources.getPrivacyBitmap(getContext(), resId); + } invalidate(); } @@ -446,6 +486,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout { bounds.set(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX2(), imageReceiver.getImageY2()); drawDuration(canvas, bounds, 1f); drawViews(canvas, bounds, 1f); + drawPrivacy(canvas, bounds, 1f); if (checkBoxBase != null && (style == STYLE_CACHE || checkBoxBase.getProgress() != 0)) { canvas.save(); @@ -474,12 +515,16 @@ public class SharedPhotoVideoCell2 extends FrameLayout { return; } + final float fwidth = bounds.width() + dp(20) * checkBoxProgress; + final float scale = bounds.width() / fwidth; + if (alpha < 1) { alpha = (float) Math.pow(alpha, 8); } canvas.save(); canvas.translate(bounds.left, bounds.top); + canvas.scale(scale, scale, 0, bounds.height()); canvas.clipRect(0, 0, bounds.width(), bounds.height()); if (currentParentColumnsCount != 9 && videoInfoLayot == null && videoText != null) { int textWidth = (int) Math.ceil(sharedResources.textPaint.measureText(videoText)); @@ -487,16 +532,9 @@ public class SharedPhotoVideoCell2 extends FrameLayout { } else if ((currentParentColumnsCount >= 9 || videoText == null) && videoInfoLayot != null) { videoInfoLayot = null; } - int width; - if (videoInfoLayot == null) { - width = dp(8); - } else { - width = dp(4) + videoInfoLayot.getWidth() + dp(4); - } - if (drawVideoIcon) { - width += dp(10); - } - canvas.translate(dp(5), dp(1) + bounds.height() - dp(17) - dp(4)); + final boolean up = viewsOnLeft(fwidth); + int width = dp(8) + (videoInfoLayot != null ? videoInfoLayot.getWidth() : 0) + (drawVideoIcon ? dp(10) : 0); + canvas.translate(dp(5), dp(1) + bounds.height() - dp(17) - dp(4) - (up ? dp(17 + 5) : 0)); AndroidUtilities.rectTmp.set(0, 0, width, dp(17)); int oldAlpha = Theme.chat_timeBackgroundPaint.getAlpha(); Theme.chat_timeBackgroundPaint.setAlpha((int) (oldAlpha * alpha)); @@ -529,11 +567,46 @@ public class SharedPhotoVideoCell2 extends FrameLayout { } } + public boolean viewsOnLeft(float width) { + if (!isStory || currentParentColumnsCount >= 5) { + return false; + } + final int viewsWidth = dp(18 + 8) + (int) viewsText.getCurrentWidth(); + final int durationWidth = showVideoLayout ? dp(8) + (videoInfoLayot != null ? videoInfoLayot.getWidth() : 0) + (drawVideoIcon ? dp(10) : 0) : 0; + final int padding = viewsWidth > 0 && durationWidth > 0 ? dp(8) : 0; + final int totalWidth = viewsWidth + padding + durationWidth; + return totalWidth > width; + } + + public void drawPrivacy(Canvas canvas, RectF bounds, float alpha) { + if (!isStory || privacyBitmap == null || privacyBitmap.isRecycled()) { + return; + } + + final float fwidth = bounds.width() + dp(20) * checkBoxProgress; + final float scale = bounds.width() / fwidth; + + final int sz = dp(17.33f * scale); + canvas.save(); + canvas.translate(bounds.right - sz - dp(5.66f), bounds.top + dp(5.66f)); + if (privacyPaint == null) { + privacyPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + } + privacyPaint.setAlpha((int) (0xFF * alpha)); + AndroidUtilities.rectTmp.set(0, 0, sz, sz); + canvas.drawBitmap(privacyBitmap, null, AndroidUtilities.rectTmp, privacyPaint); + canvas.restore(); + } + public void drawViews(Canvas canvas, RectF bounds, float alpha) { if (!isStory || imageReceiver != null && !imageReceiver.getVisible() || currentParentColumnsCount >= 5) { return; } + final float fwidth = bounds.width() + dp(20) * checkBoxProgress; + final float scale = bounds.width() / fwidth; + final boolean left = viewsOnLeft(fwidth); + float a = viewsAlpha.set(drawViews); alpha *= a; @@ -547,11 +620,12 @@ public class SharedPhotoVideoCell2 extends FrameLayout { canvas.save(); canvas.translate(bounds.left, bounds.top); + canvas.scale(scale, scale, left ? 0 : bounds.width(), bounds.height()); canvas.clipRect(0, 0, bounds.width(), bounds.height()); float width = dp(18 + 8) + viewsText.getCurrentWidth(); - canvas.translate(bounds.width() - dp(5) - width, dp(1) + bounds.height() - dp(17) - dp(4)); + canvas.translate(left ? dp(5) : bounds.width() - dp(5) - width, dp(1) + bounds.height() - dp(17) - dp(4)); AndroidUtilities.rectTmp.set(0, 0, width, dp(17)); int oldAlpha = Theme.chat_timeBackgroundPaint.getAlpha(); Theme.chat_timeBackgroundPaint.setAlpha((int) (oldAlpha * alpha)); @@ -787,6 +861,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout { Drawable viewDrawable; Paint highlightPaint = new Paint(); SparseArray imageFilters = new SparseArray<>(); + private final HashMap privacyBitmaps = new HashMap<>(); public SharedResources(Context context, Theme.ResourcesProvider resourcesProvider) { textPaint.setTextSize(dp(12)); @@ -807,6 +882,39 @@ public class SharedPhotoVideoCell2 extends FrameLayout { } return str; } + + public void recycleAll() { + for (Bitmap bitmap : privacyBitmaps.values()) { + AndroidUtilities.recycleBitmap(bitmap); + } + privacyBitmaps.clear(); + } + + public Bitmap getPrivacyBitmap(Context context, int resId) { + Bitmap bitmap = privacyBitmaps.get(resId); + if (bitmap != null) { + return bitmap; + } + bitmap = BitmapFactory.decodeResource(context.getResources(), resId); + Bitmap shadowBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(shadowBitmap); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + paint.setColorFilter(new PorterDuffColorFilter(0xFF606060, PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, 0, 0, paint); + Utilities.stackBlurBitmap(shadowBitmap, dp(1)); + Bitmap resultBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + canvas = new Canvas(resultBitmap); + canvas.drawBitmap(shadowBitmap, 0, 0, paint); + canvas.drawBitmap(shadowBitmap, 0, 0, paint); + canvas.drawBitmap(shadowBitmap, 0, 0, paint); + paint.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, 0, 0, paint); + shadowBitmap.recycle(); + bitmap.recycle(); + bitmap = resultBitmap; + privacyBitmaps.put(resId, bitmap); + return bitmap; + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java index bb74a1558..556139442 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java @@ -114,7 +114,7 @@ public class SharingLiveLocationCell extends FrameLayout { distanceTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); distanceTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(distanceTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? padding : 73, 37, LocaleController.isRTL ? 73 : padding, 0)); + addView(distanceTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? padding : 73, 33, LocaleController.isRTL ? 73 : padding, 0)); } else { addView(avatarImageView, LayoutHelper.createFrame(42, 42, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 15, 6, LocaleController.isRTL ? 15 : 0, 0)); addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? padding : 74, 17, LocaleController.isRTL ? 74 : padding, 0)); @@ -385,6 +385,9 @@ public class SharingLiveLocationCell extends FrameLayout { } } + private Drawable foreverDrawable; + private int foreverDrawableColor; + @Override protected void onDraw(Canvas canvas) { if (currentInfo == null && liveLocation == null) { @@ -399,11 +402,12 @@ public class SharingLiveLocationCell extends FrameLayout { stopTime = liveLocation.object.date + liveLocation.object.media.period; period = liveLocation.object.media.period; } + boolean forever = period == 0x7FFFFFFF; int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (stopTime < currentTime) { + if (stopTime < currentTime && !forever) { return; } - float progress = Math.abs(stopTime - currentTime) / (float) period; + float progress = forever ? 1 : Math.abs(stopTime - currentTime) / (float) period; if (LocaleController.isRTL) { rect.set(dp(13), dp(distanceTextView != null ? 18 : 12), dp(43), dp(distanceTextView != null ? 48 : 42)); } else { @@ -419,13 +423,32 @@ public class SharingLiveLocationCell extends FrameLayout { Theme.chat_radialProgress2Paint.setColor(color); Theme.chat_livePaint.setColor(color); + int a = Theme.chat_radialProgress2Paint.getAlpha(); + Theme.chat_radialProgress2Paint.setAlpha((int) (.20f * a)); + canvas.drawArc(rect, -90, 360, false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha((int) (a)); canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha(a); - String text = LocaleController.formatLocationLeftTime(stopTime - currentTime); - - float size = Theme.chat_livePaint.measureText(text); - - canvas.drawText(text, rect.centerX() - size / 2, dp(distanceTextView != null ? 37 : 31), Theme.chat_livePaint); + if (forever) { + if (foreverDrawable == null) { + foreverDrawable = getContext().getResources().getDrawable(R.drawable.filled_location_forever).mutate(); + } + if (Theme.chat_livePaint.getColor() != foreverDrawableColor) { + foreverDrawable.setColorFilter(new PorterDuffColorFilter(foreverDrawableColor = Theme.chat_livePaint.getColor(), PorterDuff.Mode.SRC_IN)); + } + foreverDrawable.setBounds( + (int) rect.centerX() - foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() - foreverDrawable.getIntrinsicHeight() / 2, + (int) rect.centerX() + foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() + foreverDrawable.getIntrinsicHeight() / 2 + ); + foreverDrawable.draw(canvas); + } else { + String text = LocaleController.formatLocationLeftTime(stopTime - currentTime); + float size = Theme.chat_livePaint.measureText(text); + canvas.drawText(text, rect.centerX() - size / 2, dp(distanceTextView != null ? 37 : 31), Theme.chat_livePaint); + } } private int getThemedColor(int key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java index ad81f6bf5..4c4a7e8cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java @@ -15,6 +15,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.os.Build; +import android.text.TextUtils; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -22,6 +23,7 @@ import android.widget.FrameLayout; import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChannelMonetizationLayout; @@ -92,7 +94,7 @@ public class SlideIntChooseView extends FrameLayout { if (options == null || whenChanged == null) { return; } - final int newValue = (int) (options.min + stepsCount * progress); + final int newValue = (int) Math.round(options.min + stepsCount * progress); if (value != newValue) { value = newValue; AndroidUtilities.vibrateCursor(seekBarView); @@ -132,19 +134,26 @@ public class SlideIntChooseView extends FrameLayout { public void updateTexts(int value, boolean animated) { minText.cancelAnimation(); - minText.setText(processText(options.minStringResId, options.min), animated); - int valueResId; - if (value <= options.min) { - valueResId = options.valueMinStringResId; - } else if (value < options.max) { - valueResId = options.valueStringResId; - } else { - valueResId = options.valueMaxStringResId; - } - valueText.cancelAnimation(); - valueText.setText(processText(valueResId, value), animated); maxText.cancelAnimation(); - maxText.setText(processText(options.maxStringResId, options.max), animated); + if (!TextUtils.isEmpty(options.resId)) { + valueText.cancelAnimation(); + valueText.setText(LocaleController.formatPluralString(options.resId, value), animated); + minText.setText("" + options.min, animated); + maxText.setText("" + options.max, animated); + } else { + int valueResId; + if (value <= options.min) { + valueResId = options.valueMinStringResId; + } else if (value < options.max) { + valueResId = options.valueStringResId; + } else { + valueResId = options.valueMaxStringResId; + } + valueText.cancelAnimation(); + valueText.setText(processText(valueResId, value), animated); + minText.setText(processText(options.minStringResId, options.min), animated); + maxText.setText(processText(options.maxStringResId, options.max), animated); + } maxText.setTextColor(Theme.getColor(value >= options.max ? Theme.key_windowBackgroundWhiteValueText : Theme.key_windowBackgroundWhiteGrayText, resourcesProvider), animated); setMaxTextEmojiSaturation(value >= options.max ? 1f : 0f, animated); } @@ -223,6 +232,8 @@ public class SlideIntChooseView extends FrameLayout { public int min; public int max; + public String resId; + public int minStringResId; public int valueMinStringResId, valueStringResId, valueMaxStringResId; public int maxStringResId; @@ -244,5 +255,17 @@ public class SlideIntChooseView extends FrameLayout { o.maxStringResId = maxStringResId; return o; } + + public static Options make( + int style, + String resId, int min, int max + ) { + Options o = new Options(); + o.style = style; + o.min = min; + o.resId = resId; + o.max = max; + return o; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java index c90069808..e4af60aee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java @@ -35,6 +35,7 @@ import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Components.ColorSpanUnderline; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ScaleStateListAnimator; import java.util.List; @@ -90,21 +91,22 @@ public class StickerSetNameCell extends FrameLayout { lp = LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, emoji ? 5 : 15, 5, emoji ? 15 : 25, 0); } addView(layout, lp); - layout.addView(textView); + layout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 1, Gravity.CENTER_VERTICAL)); editView = new TextView(context); editView.setTextColor(getThemedColor(Theme.key_chat_emojiPanelStickerSetName)); editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 11); editView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); editView.setEllipsize(TextUtils.TruncateAt.END); - editView.setPadding(dp(6.33f), 0, dp(6.33f), 0); + editView.setPadding(dp(6), 0, dp(6.33f), 0); editView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(9), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelStickerSetName), .10f), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelStickerSetName), .24f) )); editView.setGravity(Gravity.CENTER); editView.setSingleLine(true); - layout.addView(editView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 5.33f, .66f, 0, 0)); + ScaleStateListAnimator.apply(editView); + layout.addView(editView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_VERTICAL, 5, 1, 0, 0)); editView.setVisibility(View.GONE); urlTextView = new TextView(context); @@ -200,6 +202,10 @@ public class StickerSetNameCell extends FrameLayout { editView.setOnClickListener(whenClickedEdit); } + public void setHeaderOnClick(View.OnClickListener listener) { + textView.setOnClickListener(listener); + } + private void updateTextSearchSpan() { if (stickerSetName != null && stickerSetNameSearchLength > 0) { SpannableStringBuilder builder = new SpannableStringBuilder(stickerSetName); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index 1fb3230c5..45c3ea355 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -13,7 +13,9 @@ import static org.telegram.messenger.AndroidUtilities.dp; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; @@ -25,7 +27,12 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.SimpleTextView; @@ -49,7 +56,7 @@ public class TextCell extends FrameLayout { public final RLottieImageView imageView; private Switch checkBox; private ImageView valueImageView; - private int leftPadding; + public int leftPadding; private boolean needDivider; public int offsetFromImage = 71; public int heightDp = 50; @@ -644,6 +651,25 @@ public class TextCell extends FrameLayout { setValueSticker(document); } + public void setTextAndSticker(CharSequence text, String localPath, boolean divider) { + imageLeft = 21; + offsetFromImage = getOffsetFromImage(false); + textView.setText(text); + textView.setRightDrawable(null); + valueTextView.setText(valueText = null, false); + valueImageView.setVisibility(GONE); + valueTextView.setVisibility(GONE); + valueSpoilersTextView.setVisibility(GONE); + imageView.setVisibility(GONE); + imageView.setPadding(0, dp(7), 0, 0); + needDivider = divider; + setWillNotDraw(!needDivider); + if (checkBox != null) { + checkBox.setVisibility(GONE); + } + setValueSticker(localPath); + } + public void setValueSticker(TLRPC.Document document) { if (emojiDrawable == null) { emojiDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, dp(30)); @@ -655,6 +681,64 @@ public class TextCell extends FrameLayout { invalidate(); } + public void setValueSticker(String path) { + if (emojiDrawable == null) { + emojiDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, dp(30)); + if (attached) { + emojiDrawable.attach(); + } + } + ImageReceiver imageReceiver = new ImageReceiver(this); + if (isAttachedToWindow()) { + imageReceiver.onAttachedToWindow(); + } + addOnAttachStateChangeListener(new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(@NonNull View v) { + imageReceiver.onAttachedToWindow(); + } + + @Override + public void onViewDetachedFromWindow(@NonNull View v) { + imageReceiver.onDetachedFromWindow(); + } + }); + imageReceiver.setImage(path, "30_30", null, null, 0); + emojiDrawable.set(new Drawable() { + @Override + public void draw(@NonNull Canvas canvas) { + imageReceiver.setImageCoords(getBounds()); + imageReceiver.draw(canvas); + } + + @Override + public void setAlpha(int alpha) { + imageReceiver.setAlpha(alpha / (float) 0xFF); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + imageReceiver.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public int getIntrinsicWidth() { + return dp(30); + } + + @Override + public int getIntrinsicHeight() { + return dp(30); + } + }, true); + invalidate(); + } + protected int getOffsetFromImage(boolean colourful) { return colourful ? 65 : 71; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java index 10c9f0c01..9e8045e8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java @@ -33,6 +33,7 @@ import org.telegram.ui.Components.Switch; public class TextCheckCell2 extends FrameLayout { + public int id; private TextView textView; private TextView valueTextView; private Switch checkBox; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index d04e1a8c0..15cf6bc33 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -33,7 +33,6 @@ public class TextColorCell extends FrameLayout { private TextView textView; private boolean needDivider; private int currentColor; - private float alpha = 1.0f; private static Paint colorPaint; @@ -62,19 +61,6 @@ public class TextColorCell extends FrameLayout { addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 0, 21, 0)); } - @Keep - @Override - public void setAlpha(float value) { - alpha = value; - invalidate(); - } - - @Keep - @Override - public float getAlpha() { - return alpha; - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); @@ -106,7 +92,6 @@ public class TextColorCell extends FrameLayout { } if (currentColor != 0) { colorPaint.setColor(currentColor); - colorPaint.setAlpha((int) (255 * alpha)); canvas.drawCircle(LocaleController.isRTL ? AndroidUtilities.dp(33) : getMeasuredWidth() - AndroidUtilities.dp(33), getMeasuredHeight() / 2, AndroidUtilities.dp(10), colorPaint); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index 823b32079..fa478680d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -738,7 +738,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica } } - public void setCloseIcon(Runnable onClick) { + public void setCloseIcon(View.OnClickListener onClick) { if (onClick == null) { if (closeView != null) { removeView(closeView); @@ -754,7 +754,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica closeView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), Theme.RIPPLE_MASK_CIRCLE_AUTO)); addView(closeView, LayoutHelper.createFrame(30, 30, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 0)); } - closeView.setOnClickListener(v -> onClick.run()); + closeView.setOnClickListener(onClick); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index b4ba3809d..e6816f2c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -8,6 +8,10 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; +import static org.telegram.messenger.MessageObject.replaceWithLink; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -19,6 +23,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; @@ -30,16 +35,20 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; +import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.DynamicDrawableSpan; import android.text.style.ImageSpan; +import android.text.style.LineHeightSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -50,10 +59,12 @@ import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -61,6 +72,8 @@ import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.ChatListItemAnimator; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.GridLayoutManagerFixed; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScrollerCustom; import androidx.recyclerview.widget.RecyclerView; @@ -73,6 +86,7 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; @@ -82,6 +96,7 @@ import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; @@ -89,16 +104,19 @@ import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; 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.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.INavigationLayout; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -107,18 +125,23 @@ import org.telegram.ui.Cells.ChatLoadingCell; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.ChatUnreadCell; import org.telegram.ui.Components.AdminLogFilterAlert; +import org.telegram.ui.Components.AdminLogFilterAlert2; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ChatAvatarContainer; import org.telegram.ui.Components.ChatScrimPopupContainerLayout; import org.telegram.ui.Components.ClearHistoryAlert; +import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.EmbedBottomSheet; +import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.InviteLinkBottomSheet; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PhonebookShareAlert; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; +import org.telegram.ui.Components.RecyclerAnimationScrollHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SizeNotifierFrameLayout; @@ -134,6 +157,7 @@ import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; public class ChannelAdminLogActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -147,12 +171,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private RecyclerListView chatListView; private UndoView undoView; private LinearLayoutManager chatLayoutManager; + private RecyclerAnimationScrollHelper chatScrollHelper; private ChatActivityAdapter chatAdapter; private TextView bottomOverlayChatText; private ImageView bottomOverlayImage; private FrameLayout bottomOverlayChat; private FrameLayout emptyViewContainer; private ChatAvatarContainer avatarContainer; + private LinearLayout emptyLayoutView; + private ImageView emptyImageView; private TextView emptyView; private ChatActionCell floatingDateView; private ActionBarMenuItem searchItem; @@ -163,11 +190,20 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private boolean scrollingFloatingDate; private int[] mid = new int[]{2}; private boolean searchWas; + private boolean scrollByTouch; + + private float contentPanTranslation; + private float contentPanTranslationT; + private long activityResumeTime; + + + public static int lastStableId = 10; private boolean checkTextureViewPosition; private SizeNotifierFrameLayout contentView; private MessageObject selectedObject; + private TLRPC.ChannelParticipant selectedParticipant; private FrameLayout searchContainer; private ImageView searchCalendarButton; @@ -189,12 +225,16 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private boolean openAnimationEnded; - private LongSparseArray messagesDict = new LongSparseArray<>(); - private HashMap> messagesByDays = new HashMap<>(); + private final LongSparseArray messagesDict = new LongSparseArray<>(); + private final LongSparseArray realMessagesDict = new LongSparseArray<>(); + private final HashMap> messagesByDays = new HashMap<>(); protected ArrayList messages = new ArrayList<>(); + private final ArrayList filteredMessages = new ArrayList<>(); + private final HashSet expandedEvents = new HashSet<>(); private int minDate; private boolean endReached; private boolean loading; + private boolean reloadingLastMessages; private int loadsCount; private ArrayList admins; @@ -202,16 +242,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private String searchQuery = ""; private LongSparseArray selectedAdmins; - private MessageObject scrollToMessage; - - private AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(new int[]{ + private final static int[] allowedNotificationsDuringChatListAnimations = new int[]{ NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad - /*, NotificationCenter.botInfoDidLoad*/ - }); + }; + + private AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(allowedNotificationsDuringChatListAnimations); private HashMap invitesCache = new HashMap<>(); private HashMap usersMap; @@ -292,7 +331,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio Bulletin.addDelegate(this, new Bulletin.Delegate() { @Override public int getBottomOffset(int tag) { - return AndroidUtilities.dp(51); + return dp(51); } }); @@ -316,21 +355,99 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio return; } if (!TextUtils.isEmpty(searchQuery)) { - emptyView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(5), AndroidUtilities.dp(8), AndroidUtilities.dp(5)); - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("EventLogEmptyTextSearch", R.string.EventLogEmptyTextSearch, searchQuery))); + emptyImageView.setVisibility(View.GONE); + emptyView.setPadding(dp(8), dp(3), dp(8), dp(3)); + emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.NoLogFound))); } else if (selectedAdmins != null || currentFilter != null) { - emptyView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(5), AndroidUtilities.dp(8), AndroidUtilities.dp(5)); - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EventLogEmptySearch", R.string.EventLogEmptySearch))); + emptyImageView.setVisibility(View.GONE); + emptyView.setPadding(dp(8), dp(3), dp(8), dp(3)); + emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.NoLogFoundFiltered))); } else { - emptyView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); + emptyImageView.setVisibility(View.VISIBLE); + emptyView.setPadding(dp(16), dp(16), dp(16), dp(16)); if (currentChat.megagroup) { - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EventLogEmpty", R.string.EventLogEmpty))); + emptyView.setText(smallerNewNewLine(AndroidUtilities.replaceTags(getString(R.string.EventLogEmpty2)))); } else { - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EventLogEmptyChannel", R.string.EventLogEmptyChannel))); + emptyView.setText(smallerNewNewLine(AndroidUtilities.replaceTags(getString(R.string.EventLogEmptyChannel2)))); } } } + private CharSequence smallerNewNewLine(CharSequence cs) { + int index = AndroidUtilities.charSequenceIndexOf(cs, "\n\n"); + if (index >= 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (!(cs instanceof Spannable)) + cs = new SpannableStringBuilder(cs); + ((SpannableStringBuilder) cs).setSpan(new LineHeightSpan.Standard(dp(8)), index + 1, index + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return cs; + } + + public void reloadLastMessages() { + if (reloadingLastMessages) { + return; + } + reloadingLastMessages = true; + TLRPC.TL_channels_getAdminLog req = new TLRPC.TL_channels_getAdminLog(); + req.channel = MessagesController.getInputChannel(currentChat); + req.q = searchQuery; + req.limit = 10; + req.max_id = 0; + req.min_id = 0; + if (currentFilter != null) { + req.flags |= 1; + req.events_filter = currentFilter; + } + if (selectedAdmins != null) { + req.flags |= 2; + for (int a = 0; a < selectedAdmins.size(); a++) { + req.admins.add(MessagesController.getInstance(currentAccount).getInputUser(selectedAdmins.valueAt(a))); + } + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (response != null) { + final TLRPC.TL_channels_adminLogResults res = (TLRPC.TL_channels_adminLogResults) response; + AndroidUtilities.runOnUIThread(() -> { + reloadingLastMessages = false; + chatListItemAnimator.setShouldAnimateEnterFromBottom(false); + saveScrollPosition(false); + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + + ArrayList messages = new ArrayList<>(); + HashMap> messagesByDays = new HashMap<>(); + boolean added = false; + for (int a = 0; a < res.events.size(); a++) { + TLRPC.TL_channelAdminLogEvent event = res.events.get(a); + if (messagesDict.indexOfKey(event.id) >= 0) { + continue; + } + if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantToggleAdmin) { + TLRPC.TL_channelAdminLogEventActionParticipantToggleAdmin action = (TLRPC.TL_channelAdminLogEventActionParticipantToggleAdmin) event.action; + if (action.prev_participant instanceof TLRPC.TL_channelParticipantCreator && !(action.new_participant instanceof TLRPC.TL_channelParticipantCreator)) { + continue; + } + } + minEventId = Math.min(minEventId, event.id); + MessageObject messageObject = new MessageObject(currentAccount, event, messages, messagesByDays, currentChat, mid, false); + if (messageObject.contentType < 0 || messageObject.currentEvent != null && messageObject.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) { + continue; + } + if (!messagesDict.containsKey(event.id)) { + added = true; + this.messages.add(0, messageObject); + messagesDict.put(event.id, messageObject); + } + } + if (chatAdapter != null && added) { + filterDeletedMessages(); + chatAdapter.notifyDataSetChanged(); + } + }); + } + }); + } + private void loadMessages(boolean reset) { if (loading) { return; @@ -345,6 +462,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio messagesDict.clear(); messages.clear(); messagesByDays.clear(); + filterDeletedMessages(); + loadsCount = 0; } loading = true; TLRPC.TL_channels_getAdminLog req = new TLRPC.TL_channels_getAdminLog(); @@ -367,12 +486,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio req.admins.add(MessagesController.getInstance(currentAccount).getInputUser(selectedAdmins.valueAt(a))); } } + loadsCount++; updateEmptyPlaceholder(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { final TLRPC.TL_channels_adminLogResults res = (TLRPC.TL_channels_adminLogResults) response; AndroidUtilities.runOnUIThread(() -> { + loadsCount--; chatListItemAnimator.setShouldAnimateEnterFromBottom(false); + saveScrollPosition(false); MessagesController.getInstance(currentAccount).putUsers(res.users, false); MessagesController.getInstance(currentAccount).putChats(res.chats, false); boolean added = false; @@ -397,31 +519,54 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio messagesDict.put(event.id, messageObject); } int newRowsCount = messages.size() - oldRowsCount; + + ArrayList missingReplies = new ArrayList<>(); + for (int i = oldRowsCount; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg != null && msg.contentType != 0 && msg.getRealId() >= 0) { + realMessagesDict.put(msg.getRealId(), msg); + } + if (msg == null || msg.messageOwner == null || msg.messageOwner.reply_to == null) { + continue; + } + TLRPC.MessageReplyHeader replyTo = msg.messageOwner.reply_to; + if (replyTo.reply_to_peer_id == null) { + MessageObject replyMessage = null; + for (int j = 0; j < messages.size(); ++j) { + if (i == j) continue; + MessageObject msg2 = messages.get(j); + if (msg2.contentType != 1 && msg2.getRealId() == replyTo.reply_to_msg_id) { + replyMessage = msg2; + break; + } + } + if (replyMessage != null) { + msg.replyMessageObject = replyMessage; + } + } + missingReplies.add(msg); + } + if (!missingReplies.isEmpty()) { + MediaDataController.getInstance(currentAccount).loadReplyMessagesForMessages(missingReplies, -currentChat.id, ChatActivity.MODE_DEFAULT, 0, () -> { + saveScrollPosition(false); + chatAdapter.notifyDataSetChanged(); + }, getClassGuid()); + } + filterDeletedMessages(); + loading = false; if (!added) { endReached = true; } AndroidUtilities.updateViewVisibilityAnimated(progressView, false, 0.3f, true); chatListView.setEmptyView(emptyViewContainer); - if (newRowsCount != 0) { - boolean end = false; - if (endReached) { - end = true; - chatAdapter.notifyItemRangeChanged(0, 2); - } - int firstVisPos = chatLayoutManager.findLastVisibleItemPosition(); - View firstVisView = chatLayoutManager.findViewByPosition(firstVisPos); - int top = ((firstVisView == null) ? 0 : firstVisView.getTop()) - chatListView.getPaddingTop(); - if (newRowsCount - (end ? 1 : 0) > 0) { - int insertStart = 1 + (end ? 0 : 1); - chatAdapter.notifyItemChanged(insertStart); - chatAdapter.notifyItemRangeInserted(insertStart, newRowsCount - (end ? 1 : 0)); - } - if (firstVisPos != -1) { - chatLayoutManager.scrollToPositionWithOffset(firstVisPos + newRowsCount - (end ? 1 : 0), top); - } - } else if (endReached) { - chatAdapter.notifyItemRemoved(0); + + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(); + } + + if (searchItem != null) { + searchItem.setVisibility(filteredMessages.isEmpty() && TextUtils.isEmpty(searchQuery) ? View.GONE : View.VISIBLE); } }); } @@ -431,6 +576,172 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } + private final ArrayList filteredMessagesUpdatedPosition = new ArrayList<>(); + private void filterDeletedMessages() { + ArrayList newFilteredMessages = new ArrayList<>(); + + ArrayList currentDeleteGroup = new ArrayList<>(); + filteredMessagesUpdatedPosition.clear(); + for (int i = 0; i < messages.size(); ++i) { + MessageObject message = messages.get(i); + long thisMessageDeletedBy = messageDeletedBy(message); + + if (message.stableId <= 0) { + message.stableId = lastStableId++; + } + + MessageObject nextMessage = i + 1 < messages.size() ? messages.get(i + 1) : null; + long nextMessageDeletedBy = messageDeletedBy(nextMessage); + + if (thisMessageDeletedBy != 0) { + currentDeleteGroup.add(message); + } else { + newFilteredMessages.add(message); + } + if (thisMessageDeletedBy != nextMessageDeletedBy && !currentDeleteGroup.isEmpty()) { + boolean wasKeyboard = message.messageOwner.reply_markup != null && !(message.messageOwner.reply_markup.rows.isEmpty()); + int index = newFilteredMessages.size(); + ArrayList separatedFirstActions = new ArrayList<>(); + for (int j = currentDeleteGroup.size() - 1; j >= 0; j--) { + if (currentDeleteGroup.get(j).contentType == 1) { + separatedFirstActions.add(currentDeleteGroup.remove(j)); + } else { + break; + } + } + if (!currentDeleteGroup.isEmpty()) { + MessageObject lastMessage = currentDeleteGroup.get(currentDeleteGroup.size() - 1); + boolean expandable = TextUtils.isEmpty(searchQuery) && currentDeleteGroup.size() > 3; + if (expandedEvents.contains(lastMessage.eventId) || !expandable) { + for (int k = 0; k < currentDeleteGroup.size(); ++k) { + setupExpandButton(currentDeleteGroup.get(k), 0); + } + newFilteredMessages.addAll(currentDeleteGroup); + } else { + setupExpandButton(lastMessage, currentDeleteGroup.size() - 1); + newFilteredMessages.add(lastMessage); + } + if (wasKeyboard != (lastMessage.messageOwner.reply_markup != null && !(lastMessage.messageOwner.reply_markup.rows.isEmpty()))) { + lastMessage.forceUpdate = true; + chatAdapter.notifyItemChanged(index + (wasKeyboard ? currentDeleteGroup.size() - 1 : 0)); + chatAdapter.notifyItemChanged(index + (wasKeyboard ? currentDeleteGroup.size() - 1 : 0) + 1); + } + newFilteredMessages.add(actionMessagesDeletedBy(message.eventId, message.currentEvent.user_id, currentDeleteGroup, expandedEvents.contains(message.eventId), expandable)); + } + if (!separatedFirstActions.isEmpty()) { + MessageObject lastMessage = separatedFirstActions.get(separatedFirstActions.size() - 1); + newFilteredMessages.addAll(separatedFirstActions); + newFilteredMessages.add(actionMessagesDeletedBy(lastMessage.eventId, lastMessage.currentEvent.user_id, separatedFirstActions, true, false)); + } + currentDeleteGroup.clear(); + } + } + filteredMessages.clear(); + filteredMessages.addAll(newFilteredMessages); + } + + private final LongSparseArray stableIdByEventExpand = new LongSparseArray<>(); + private MessageObject actionMessagesDeletedBy(long eventId, long user_id, ArrayList messages, boolean expanded, boolean expandable) { + MessageObject messageObject = null; + for (int i = 0; i < filteredMessages.size(); ++i) { + MessageObject messageObject1 = filteredMessages.get(i); + if (messageObject1 != null && messageObject1.contentType == 1 && messageObject1.actionDeleteGroupEventId == eventId) { + messageObject = messageObject1; + break; + } + } + if (messageObject == null) { + TLRPC.TL_message msg = new TLRPC.TL_message(); + msg.dialog_id = -currentChat.id; + msg.id = -1; + try { + msg.date = messages.get(0).messageOwner.date; + } catch (Exception e) { + FileLog.e(e); + } + messageObject = new MessageObject(currentAccount, msg, false, false); + } + TLRPC.User user = getMessagesController().getUser(user_id); + messageObject.contentType = 1; + if (expandable && messages.size() > 1) { + messageObject.actionDeleteGroupEventId = eventId; + } else { + messageObject.actionDeleteGroupEventId = -1; + } + String names = TextUtils.join(", ", messages.stream().map(MessageObject::getFromChatId).distinct().map(dialogId -> { + if (dialogId < 0) { + TLRPC.Chat chat = getMessagesController().getChat(-dialogId); + if (chat == null) return null; + return chat.title; + } else { + return UserObject.getForcedFirstName(getMessagesController().getUser(dialogId)); + } + }).filter(s -> s != null).limit(4).toArray()); + SpannableStringBuilder ssb = new SpannableStringBuilder(replaceWithLink(LocaleController.formatPluralString(expandable ? "EventLogDeletedMultipleMessagesToExpand" : "EventLogDeletedMultipleMessages", messages.size(), names), "un1", user)); + if (expandable && messages.size() > 1) { + ProfileActivity.ShowDrawable drawable = findDrawable(messageObject.messageText); + if (drawable == null) { + drawable = new ProfileActivity.ShowDrawable(getString(expanded ? R.string.EventLogDeletedMultipleMessagesHide : R.string.EventLogDeletedMultipleMessagesShow)); + drawable.textDrawable.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + drawable.textDrawable.setTextSize(dp(10)); + drawable.setTextColor(Color.WHITE); + drawable.setBackgroundColor(0x1e000000); + } else { + drawable.textDrawable.setText(getString(expanded ? R.string.EventLogDeletedMultipleMessagesHide : R.string.EventLogDeletedMultipleMessagesShow), false); + } + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + ssb.append(" S"); + ssb.setSpan(new ColoredImageSpan(drawable), ssb.length() - 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + messageObject.messageText = ssb; + MessageObject lastMessage = messages.size() <= 0 ? null : messages.get(messages.size() - 1); + if (lastMessage != null) { + if (!stableIdByEventExpand.containsKey(lastMessage.eventId)) + stableIdByEventExpand.put(lastMessage.eventId, lastStableId++); + messageObject.stableId = stableIdByEventExpand.get(lastMessage.eventId); + } + return messageObject; + } + + public static ProfileActivity.ShowDrawable findDrawable(CharSequence messageText) { + if (messageText instanceof Spannable) { + ColoredImageSpan[] spans = ((Spannable) messageText).getSpans(0, messageText.length(), ColoredImageSpan.class); + for (int i = 0; i < spans.length; ++i) { + if (spans[i] != null && spans[i].drawable instanceof ProfileActivity.ShowDrawable) { + return (ProfileActivity.ShowDrawable) spans[i].drawable; + } + } + } + return null; + } + + private void setupExpandButton(MessageObject msg, int count) { + if (msg == null) { + return; + } + if (count <= 0) { + if (msg.messageOwner.reply_markup != null) { + msg.messageOwner.reply_markup.rows.clear(); + } + } else { + TLRPC.TL_replyInlineMarkup markup = new TLRPC.TL_replyInlineMarkup(); + msg.messageOwner.reply_markup = markup; + TLRPC.TL_keyboardButtonRow row = new TLRPC.TL_keyboardButtonRow(); + markup.rows.add(row); + TLRPC.TL_keyboardButton button = new TLRPC.TL_keyboardButton(); + button.text = LocaleController.formatPluralString("EventLogExpandMore", count); + row.buttons.add(button); + } + msg.measureInlineBotButtons(); + } + + private long messageDeletedBy(MessageObject msg) { + if (msg == null || msg.currentEvent == null || !(msg.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage)) { + return 0; + } + return msg.currentEvent.user_id; + } + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.emojiLoaded) { @@ -593,15 +904,68 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio //updateSearchButtons(0, 0, 0); } }); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(getString("Search", R.string.Search)); avatarContainer.setEnabled(false); avatarContainer.setTitle(currentChat.title); - avatarContainer.setSubtitle(LocaleController.getString("EventLogAllEvents", R.string.EventLogAllEvents)); + avatarContainer.setSubtitle(getString("EventLogAllEvents", R.string.EventLogAllEvents)); avatarContainer.setChatAvatar(currentChat); fragmentView = new SizeNotifierFrameLayout(context) { + final AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { + + @Override + protected void onTransitionStart(boolean keyboardVisible, int contentHeight) { + wasManualScroll = true; + } + + @Override + protected void onTransitionEnd() { + + } + + @Override + protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { + if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { + return; + } + contentPanTranslation = y; + contentPanTranslationT = progress; + actionBar.setTranslationY(y); + if (emptyViewContainer != null) { + emptyViewContainer.setTranslationY(y / 2); + } + progressView.setTranslationY(y / 2); + contentView.setBackgroundTranslation((int) y); + setFragmentPanTranslationOffset((int) y); +// invalidateChatListViewTopPadding(); +// invalidateMessagesVisiblePart(); + chatListView.invalidate(); +// updateBulletinLayout(); + if (AndroidUtilities.isTablet() && getParentActivity() instanceof LaunchActivity) { + BaseFragment mainFragment = ((LaunchActivity)getParentActivity()).getActionBarLayout().getLastFragment(); + if (mainFragment instanceof DialogsActivity) { + ((DialogsActivity)mainFragment).setPanTranslationOffset(y); + } + } + } + + @Override + protected boolean heightAnimationEnabled() { + INavigationLayout actionBarLayout = getParentLayout(); + if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null) { + return false; + } + if (System.currentTimeMillis() - activityResumeTime < 250) { + return false; + } + if ((ChannelAdminLogActivity.this == actionBarLayout.getLastFragment() && actionBarLayout.isTransitionAnimationInProgress()) || actionBarLayout.isPreviewOpenAnimationInProgress() || isPaused || !openAnimationEnded) { + return false; + } + return true; + } + }; @Override protected void onAttachedToWindow() { @@ -650,7 +1014,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } if (child == chatListView || child == progressView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); - int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - AndroidUtilities.dp(48 + 2)), MeasureSpec.EXACTLY); + int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(dp(10), heightSize - dp(48 + 2)), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == emptyViewContainer) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); @@ -717,7 +1081,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } if (child == emptyViewContainer) { - childTop -= AndroidUtilities.dp(24) - (actionBar.getVisibility() == VISIBLE ? actionBar.getMeasuredHeight() / 2 : 0); + childTop -= dp(24) - (actionBar.getVisibility() == VISIBLE ? actionBar.getMeasuredHeight() / 2 : 0); } else if (child == actionBar) { childTop -= getPaddingTop(); } else if (child == backgroundView) { @@ -750,16 +1114,39 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio contentView.addView(emptyViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); emptyViewContainer.setOnTouchListener((v, event) -> true); - emptyView = new TextView(context); + emptyLayoutView = new LinearLayout(context); + emptyLayoutView.setBackground(Theme.createServiceDrawable(dp(12), emptyView, contentView)); + emptyLayoutView.setOrientation(LinearLayout.VERTICAL); + + emptyImageView = new ImageView(context); + emptyImageView.setScaleType(ImageView.ScaleType.CENTER); + emptyImageView.setImageResource(R.drawable.large_log_actions); + emptyImageView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); + emptyImageView.setVisibility(View.GONE); + emptyLayoutView.addView(emptyImageView, LayoutHelper.createLinear(54, 54, Gravity.CENTER, 16, 20, 16, -4)); + + emptyView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(Math.min(MeasureSpec.getSize(widthMeasureSpec), dp(220)), MeasureSpec.getMode(widthMeasureSpec)), heightMeasureSpec); + } + }; emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(Theme.getColor(Theme.key_chat_serviceText)); - emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView)); - emptyView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); - emptyViewContainer.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 16, 0, 16, 0)); + emptyView.setPadding(dp(8), dp(5), dp(8), dp(5)); + emptyLayoutView.addView(emptyView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 0)); + + emptyViewContainer.addView(emptyLayoutView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 0)); chatListView = new RecyclerListView(context) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + applyScrolledPosition(); + super.onLayout(changed, l, t, r, b); + } + @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean result = super.drawChild(canvas, child, drawingTime); @@ -767,6 +1154,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio ChatMessageCell chatMessageCell = (ChatMessageCell) child; ImageReceiver imageReceiver = chatMessageCell.getAvatarImage(); if (imageReceiver != null) { + boolean updateVisibility = !chatMessageCell.getMessageObject().deleted && chatListView.getChildAdapterPosition(chatMessageCell) != RecyclerView.NO_POSITION; if (chatMessageCell.getMessageObject().deleted) { imageReceiver.setVisible(false, false); return result; @@ -839,8 +1227,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } } - if (y - AndroidUtilities.dp(48) < top) { - y = top + AndroidUtilities.dp(48); + if (y - dp(48) < top) { + y = top + dp(48); } if (!chatMessageCell.drawPinnedBottom()) { int cellBottom = (int) (chatMessageCell.getY() + chatMessageCell.getMeasuredHeight()); @@ -857,7 +1245,9 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio y -= chatMessageCell.getTranslationY(); } } - imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + if (updateVisibility) { + imageReceiver.setImageY(y - dp(44)); + } if (chatMessageCell.shouldDrawAlphaLayer()) { imageReceiver.setAlpha(chatMessageCell.getAlpha()); canvas.scale( @@ -867,7 +1257,9 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } else { imageReceiver.setAlpha(1f); } - imageReceiver.setVisible(true, false); + if (updateVisibility) { + imageReceiver.setVisible(true, false); + } imageReceiver.draw(canvas); canvas.restore(); } @@ -878,6 +1270,20 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio chatListView.setOnItemClickListener(new RecyclerListView.OnItemClickListenerExtended() { @Override public void onItemClick(View view, int position, float x, float y) { + if (view instanceof ChatActionCell) { + MessageObject messageObject = ((ChatActionCell) view).getMessageObject(); + if (messageObject != null && messageObject.actionDeleteGroupEventId != -1) { + if (expandedEvents.contains(messageObject.actionDeleteGroupEventId)) { + expandedEvents.remove(messageObject.actionDeleteGroupEventId); + } else { + expandedEvents.add(messageObject.actionDeleteGroupEventId); + } + saveScrollPosition(true); + filterDeletedMessages(); + chatAdapter.notifyDataSetChanged(); + return; + } + } createMenu(view, x, y); } }); @@ -885,15 +1291,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio chatListView.setVerticalScrollBarEnabled(true); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); - chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(3)); - chatListView.setItemAnimator(chatListItemAnimator = new ChatListItemAnimator(null, chatListView, null) { + chatListView.setPadding(0, dp(4), 0, dp(3)); + chatListView.setItemAnimator(chatListItemAnimator = new ChatListItemAnimator(null, chatListView, resourceProvider) { int scrollAnimationIndex = -1; Runnable finishRunnable; public void onAnimationStart() { if (scrollAnimationIndex == -1) { - scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, null, false); + scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, allowedNotificationsDuringChatListAnimations, false); } if (finishRunnable != null) { AndroidUtilities.cancelRunOnUIThread(finishRunnable); @@ -931,19 +1337,28 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + scrollByTouch = false; LinearSmoothScrollerCustom linearSmoothScroller = new LinearSmoothScrollerCustom(recyclerView.getContext(), LinearSmoothScrollerCustom.POSITION_MIDDLE); linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); } + + @Override + public void scrollToPositionWithOffset(int position, int offset) { + super.scrollToPositionWithOffset(position, offset); + } }; chatLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); chatLayoutManager.setStackFromEnd(true); chatListView.setLayoutManager(chatLayoutManager); + chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager); + chatScrollHelper.setScrollListener(this::updateMessagesVisiblePart); + chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { private float totalDy = 0; - private final int scrollValue = AndroidUtilities.dp(100); + private final int scrollValue = dp(100); @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { @@ -994,11 +1409,11 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio contentView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); progressView2 = new View(context); - progressView2.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(18), progressView2, contentView)); + progressView2.setBackground(Theme.createServiceDrawable(dp(18), progressView2, contentView)); progressView.addView(progressView2, LayoutHelper.createFrame(36, 36, Gravity.CENTER)); progressBar = new RadialProgressView(context); - progressBar.setSize(AndroidUtilities.dp(28)); + progressBar.setSize(dp(28)); progressBar.setProgressColor(Theme.getColor(Theme.key_chat_serviceText)); progressView.addView(progressBar, LayoutHelper.createFrame(32, 32, Gravity.CENTER)); @@ -1019,21 +1434,21 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } }; bottomOverlayChat.setWillNotDraw(false); - bottomOverlayChat.setPadding(0, AndroidUtilities.dp(3), 0, 0); + bottomOverlayChat.setPadding(0, dp(3), 0, 0); contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); bottomOverlayChat.setOnClickListener(view -> { if (getParentActivity() == null) { return; } - AdminLogFilterAlert adminLogFilterAlert = new AdminLogFilterAlert(getParentActivity(), currentFilter, selectedAdmins, currentChat.megagroup); + AdminLogFilterAlert2 adminLogFilterAlert = new AdminLogFilterAlert2(this, currentFilter, selectedAdmins, currentChat.megagroup); adminLogFilterAlert.setCurrentAdmins(admins); adminLogFilterAlert.setAdminLogFilterAlertDelegate((filter, admins) -> { currentFilter = filter; selectedAdmins = admins; if (currentFilter != null || selectedAdmins != null) { - avatarContainer.setSubtitle(LocaleController.getString("EventLogSelectedEvents", R.string.EventLogSelectedEvents)); + avatarContainer.setSubtitle(getString("EventLogSelectedEvents", R.string.EventLogSelectedEvents)); } else { - avatarContainer.setSubtitle(LocaleController.getString("EventLogAllEvents", R.string.EventLogAllEvents)); + avatarContainer.setSubtitle(getString("EventLogAllEvents", R.string.EventLogAllEvents)); } loadMessages(true); }); @@ -1044,7 +1459,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio bottomOverlayChatText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); bottomOverlayChatText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); bottomOverlayChatText.setTextColor(Theme.getColor(Theme.key_chat_fieldOverlayText)); - bottomOverlayChatText.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS).toUpperCase()); + bottomOverlayChatText.setText(getString("SETTINGS", R.string.SETTINGS).toUpperCase()); bottomOverlayChat.addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); bottomOverlayImage = new ImageView(context); @@ -1052,16 +1467,16 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio bottomOverlayImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_fieldOverlayText), PorterDuff.Mode.MULTIPLY)); bottomOverlayImage.setScaleType(ImageView.ScaleType.CENTER); bottomOverlayChat.addView(bottomOverlayImage, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 3, 0, 0, 0)); - bottomOverlayImage.setContentDescription(LocaleController.getString("BotHelp", R.string.BotHelp)); + bottomOverlayImage.setContentDescription(getString("BotHelp", R.string.BotHelp)); bottomOverlayImage.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); if (currentChat.megagroup) { - builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("EventLogInfoDetail", R.string.EventLogInfoDetail))); + builder.setMessage(AndroidUtilities.replaceTags(getString("EventLogInfoDetail", R.string.EventLogInfoDetail))); } else { - builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("EventLogInfoDetailChannel", R.string.EventLogInfoDetailChannel))); + builder.setMessage(AndroidUtilities.replaceTags(getString("EventLogInfoDetailChannel", R.string.EventLogInfoDetailChannel))); } - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - builder.setTitle(LocaleController.getString("EventLogInfoTitle", R.string.EventLogInfoTitle)); + builder.setPositiveButton(getString("OK", R.string.OK), null); + builder.setTitle(getString("EventLogInfoTitle", R.string.EventLogInfoTitle)); showDialog(builder.create()); }); @@ -1079,7 +1494,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio searchContainer.setFocusable(true); searchContainer.setFocusableInTouchMode(true); searchContainer.setClickable(true); - searchContainer.setPadding(0, AndroidUtilities.dp(3), 0, 0); + searchContainer.setPadding(0, dp(3), 0, 0); contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); /*searchUpButton = new ImageView(context); @@ -1136,7 +1551,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); undoView = new UndoView(context); - undoView.setAdditionalTranslationY(AndroidUtilities.dp(51)); + undoView.setAdditionalTranslationY(dp(51)); contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); updateEmptyPlaceholder(); @@ -1165,6 +1580,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private final static int OPTION_CALL = 17; private final static int OPTION_RESTRICT = 33; private final static int OPTION_REPORT_FALSE_POSITIVE = 34; + private final static int OPTION_BAN = 35; private boolean createMenu(View v) { return createMenu(v, 0, 0); @@ -1195,15 +1611,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio SpannableString arrow = new SpannableString(">"); Drawable arrowDrawable = getContext().getResources().getDrawable(R.drawable.attach_arrow_right).mutate(); arrowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_undo_cancelColor), PorterDuff.Mode.MULTIPLY)); - arrowDrawable.setBounds(0, 0, AndroidUtilities.dp(10), AndroidUtilities.dp(10)); + arrowDrawable.setBounds(0, 0, dp(10), dp(10)); arrow.setSpan(new ImageSpan(arrowDrawable, DynamicDrawableSpan.ALIGN_CENTER), 0, arrow.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); SpannableStringBuilder link = new SpannableStringBuilder(); link - .append(LocaleController.getString("EventLogFilterGroupInfo", R.string.EventLogFilterGroupInfo)) + .append(getString("EventLogFilterGroupInfo", R.string.EventLogFilterGroupInfo)) .append(" ") .append(arrow) .append(" ") - .append(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators)); + .append(getString("ChannelAdministrators", R.string.ChannelAdministrators)); link.setSpan(new ClickableSpan() { @Override public void onClick(@NonNull View view) { @@ -1216,14 +1632,14 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio ds.setUnderlineText(false); } }, 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - CharSequence text = LocaleController.getString("ChannelAntiSpamInfo2", R.string.ChannelAntiSpamInfo2); + CharSequence text = getString("ChannelAntiSpamInfo2", R.string.ChannelAntiSpamInfo2); text = AndroidUtilities.replaceCharSequence("%s", text, link); - Bulletin bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, LocaleController.getString("ChannelAntiSpamUser", R.string.ChannelAntiSpamUser), text); + Bulletin bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, getString("ChannelAntiSpamUser", R.string.ChannelAntiSpamUser), text); bulletin.setDuration(Bulletin.DURATION_PROLONG); bulletin.show(); return true; } - items.add(LocaleController.getString("ReportFalsePositive", R.string.ReportFalsePositive)); + items.add(getString("ReportFalsePositive", R.string.ReportFalsePositive)); icons.add(R.drawable.msg_notspam); options.add(OPTION_REPORT_FALSE_POSITIVE); items.add(null); @@ -1232,10 +1648,11 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } if (selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.caption != null) { - items.add(LocaleController.getString("Copy", R.string.Copy)); + items.add(getString("Copy", R.string.Copy)); icons.add(R.drawable.msg_copy); options.add(OPTION_COPY); } + if (type == 1) { if (selectedObject.currentEvent != null && selectedObject.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionChangeStickerSet) { TLRPC.TL_channelAdminLogEventActionChangeStickerSet action = (TLRPC.TL_channelAdminLogEventActionChangeStickerSet) selectedObject.currentEvent.action; @@ -1272,77 +1689,77 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } else if (type == 3) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { - items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + items.add(getString("SaveToGIFs", R.string.SaveToGIFs)); icons.add(R.drawable.msg_gif); options.add(OPTION_SAVE_TO_GIFS); } } else if (type == 4) { if (selectedObject.isVideo()) { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(getString("SaveToGallery", R.string.SaveToGallery)); icons.add(R.drawable.msg_gallery); options.add(OPTION_SAVE_TO_GALLERY); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (selectedObject.isMusic()) { - items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); + items.add(getString("SaveToMusic", R.string.SaveToMusic)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (selectedObject.getDocument() != null) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { - items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + items.add(getString("SaveToGIFs", R.string.SaveToGIFs)); icons.add(R.drawable.msg_gif); options.add(OPTION_SAVE_TO_GIFS); } - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(getString("SaveToGallery", R.string.SaveToGallery)); icons.add(R.drawable.msg_gallery); options.add(OPTION_SAVE_TO_GALLERY); } } else if (type == 5) { - items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); + items.add(getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); icons.add(R.drawable.msg_language); options.add(OPTION_APPLY_FILE); - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (type == 10) { - items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); + items.add(getString("ApplyThemeFile", R.string.ApplyThemeFile)); icons.add(R.drawable.msg_theme); options.add(OPTION_APPLY_FILE); - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (type == 6) { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(getString("SaveToGallery", R.string.SaveToGallery)); icons.add(R.drawable.msg_gallery); options.add(OPTION_SAVE_TO_GALLERY2); - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (type == 7) { if (selectedObject.isMask()) { - items.add(LocaleController.getString("AddToMasks", R.string.AddToMasks)); + items.add(getString("AddToMasks", R.string.AddToMasks)); } else { - items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); + items.add(getString("AddToStickers", R.string.AddToStickers)); } icons.add(R.drawable.msg_sticker); options.add(OPTION_SAVE_STICKER); @@ -1353,15 +1770,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio user = MessagesController.getInstance(currentAccount).getUser(uid); } if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && ContactsController.getInstance(currentAccount).contactsDict.get(user.id) == null) { - items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); + items.add(getString("AddContactTitle", R.string.AddContactTitle)); icons.add(R.drawable.msg_addcontact); options.add(OPTION_ADD_CONTACT); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { - items.add(LocaleController.getString("Copy", R.string.Copy)); + items.add(getString("Copy", R.string.Copy)); icons.add(R.drawable.msg_copy); options.add(OPTION_COPY_PHONE); - items.add(LocaleController.getString("Call", R.string.Call)); + items.add(getString("Call", R.string.Call)); icons.add(R.drawable.msg_calls); options.add(OPTION_CALL); } @@ -1370,12 +1787,12 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio boolean callbackSent = false; Runnable proceed = () -> { - if (options.isEmpty()) { + if (options.isEmpty() || getParentActivity() == null) { return; } ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, getResourceProvider(), 0); - popupLayout.setMinimumWidth(AndroidUtilities.dp(200)); + popupLayout.setMinimumWidth(dp(200)); Rect backgroundPaddings = new Rect(); Drawable shadowDrawable = getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); shadowDrawable.getPadding(backgroundPaddings); @@ -1386,8 +1803,11 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio popupLayout.addView(new ActionBarPopupWindow.GapView(getContext(), getResourceProvider()), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } else { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1, getResourceProvider()); - cell.setMinimumWidth(AndroidUtilities.dp(200)); + cell.setMinimumWidth(dp(200)); cell.setTextAndIcon(items.get(a), icons.get(a)); + if (options.get(a) == OPTION_BAN) { + cell.setColors(getThemedColor(Theme.key_text_RedBold), getThemedColor(Theme.key_text_RedRegular)); + } final Integer option = options.get(a); popupLayout.addView(cell); final int i = a; @@ -1438,17 +1858,17 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio scrimPopupWindow.setClippingEnabled(true); scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); scrimPopupWindow.setFocusable(true); - scrimPopupContainerLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + scrimPopupContainerLayout.measure(View.MeasureSpec.makeMeasureSpec(dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(dp(1000), View.MeasureSpec.AT_MOST)); scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); scrimPopupWindow.getContentView().setFocusableInTouchMode(true); popupLayout.setFitItems(true); - int popupX = v.getLeft() + (int) x - scrimPopupContainerLayout.getMeasuredWidth() + backgroundPaddings.left - AndroidUtilities.dp(28); - if (popupX < AndroidUtilities.dp(6)) { - popupX = AndroidUtilities.dp(6); - } else if (popupX > chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth()) { - popupX = chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth(); + int popupX = v.getLeft() + (int) x - scrimPopupContainerLayout.getMeasuredWidth() + backgroundPaddings.left - dp(28); + if (popupX < dp(6)) { + popupX = dp(6); + } else if (popupX > chatListView.getMeasuredWidth() - dp(6) - scrimPopupContainerLayout.getMeasuredWidth()) { + popupX = chatListView.getMeasuredWidth() - dp(6) - scrimPopupContainerLayout.getMeasuredWidth(); } if (AndroidUtilities.isTablet()) { int[] location = new int[2]; @@ -1456,21 +1876,21 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio popupX += location[0]; } int totalHeight = contentView.getHeight(); - int height = scrimPopupContainerLayout.getMeasuredHeight() + AndroidUtilities.dp(48); + int height = scrimPopupContainerLayout.getMeasuredHeight() + dp(48); int keyboardHeight = contentView.measureKeyboardHeight(); - if (keyboardHeight > AndroidUtilities.dp(20)) { + if (keyboardHeight > dp(20)) { totalHeight += keyboardHeight; } int popupY; if (height < totalHeight) { popupY = (int) (chatListView.getY() + v.getTop() + y); - if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { - popupY += AndroidUtilities.dp(240) - height; + if (height - backgroundPaddings.top - backgroundPaddings.bottom > dp(240)) { + popupY += dp(240) - height; } - if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { - popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); - } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { - popupY = totalHeight - height - AndroidUtilities.dp(8); + if (popupY < chatListView.getY() + dp(24)) { + popupY = (int) (chatListView.getY() + dp(24)); + } else if (popupY > totalHeight - height - dp(8)) { + popupY = totalHeight - height - dp(8); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; @@ -1484,20 +1904,27 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if ( ChatObject.canBlockUsers(currentChat) && - message.currentEvent != null && message.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage && message.currentEvent.user_id == getMessagesController().telegramAntispamUserId && - message.messageOwner != null && message.messageOwner.from_id != null && !UserObject.isUserSelf(getMessagesController().getUser(message.messageOwner.from_id.user_id)) + message.currentEvent != null && message.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage && + message.messageOwner != null && message.messageOwner.from_id != null ) { TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.from_id.user_id); - if (user != null) { + if (user != null && !UserObject.isUserSelf(user)) { callbackSent = true; - getMessagesController().checkIsInChat(true, currentChat, user, (isInChat, rights, rank) -> { - if (isInChat) { - items.add(LocaleController.getString("BanUser", R.string.BanUser)); - icons.add(R.drawable.msg_block2); - options.add(OPTION_RESTRICT); + getMessagesController().getChannelParticipant(currentChat, user, participant -> AndroidUtilities.runOnUIThread(() -> { + selectedParticipant = participant; + if (participant != null) { + if (ChatObject.canUserDoAction(currentChat, participant, ChatObject.ACTION_SEND) || ChatObject.canUserDoAction(currentChat, participant, ChatObject.ACTION_SEND_MEDIA)) { + items.add(getString(R.string.Restrict)); + icons.add(R.drawable.msg_block2); + options.add(OPTION_RESTRICT); + } + + items.add(getString(R.string.Ban)); + icons.add(R.drawable.msg_block); + options.add(OPTION_BAN); } - AndroidUtilities.runOnUIThread(proceed); - }); + proceed.run(); + })); } } if (!callbackSent) { @@ -1630,7 +2057,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio switch (option) { case OPTION_COPY: { AndroidUtilities.addToClipboard(getMessageContent(selectedObject, 0, true)); - BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(LocaleController.getString("MessageCopied", R.string.MessageCopied)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(getString("MessageCopied", R.string.MessageCopied)).show(); break; } case OPTION_SAVE_TO_GALLERY: { @@ -1648,6 +2075,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; + selectedParticipant = null; return; } MediaController.saveFile(path, getParentActivity(), selectedObject.type == MessageObject.TYPE_VIDEO ? 1 : 0, null, null); @@ -1691,12 +2119,13 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio scrollToPositionOnRecreate = -1; if (getParentActivity() == null) { selectedObject = null; + selectedParticipant = null; return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("IncorrectTheme", R.string.IncorrectTheme)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setTitle(getString("AppName", R.string.AppName)); + builder.setMessage(getString("IncorrectTheme", R.string.IncorrectTheme)); + builder.setPositiveButton(getString("OK", R.string.OK), null); showDialog(builder.create()); } } else { @@ -1705,12 +2134,13 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } else { if (getParentActivity() == null) { selectedObject = null; + selectedParticipant = null; return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("IncorrectLocalization", R.string.IncorrectLocalization)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setTitle(getString("AppName", R.string.AppName)); + builder.setMessage(getString("IncorrectLocalization", R.string.IncorrectLocalization)); + builder.setPositiveButton(getString("OK", R.string.OK), null); showDialog(builder.create()); } } @@ -1741,7 +2171,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path))); } try { - getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("ShareFile", R.string.ShareFile)), 500); + getParentActivity().startActivityForResult(Intent.createChooser(intent, getString("ShareFile", R.string.ShareFile)), 500); } catch (Exception e) { } @@ -1761,6 +2191,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; + selectedParticipant = null; return; } MediaController.saveFile(path, getParentActivity(), 0, null, null); @@ -1774,6 +2205,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; + selectedParticipant = null; return; } String fileName = FileLoader.getDocumentFileName(selectedObject.getDocument()); @@ -1808,7 +2240,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } case OPTION_COPY_PHONE: { AndroidUtilities.addToClipboard(selectedObject.messageOwner.media.phone_number); - BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(LocaleController.getString("PhoneCopied", R.string.PhoneCopied)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(getString("PhoneCopied", R.string.PhoneCopied)).show(); break; } case OPTION_CALL: { @@ -1828,18 +2260,47 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio getConnectionsManager().sendRequest(req, (res, err) -> { AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.TL_boolTrue) { - BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, LocaleController.getString("ChannelAntiSpamFalsePositiveReported", R.string.ChannelAntiSpamFalsePositiveReported)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, getString("ChannelAntiSpamFalsePositiveReported", R.string.ChannelAntiSpamFalsePositiveReported)).show(); } else if (res instanceof TLRPC.TL_boolFalse) { - BulletinFactory.of(this).createSimpleBulletin(R.raw.error, LocaleController.getString("UnknownError", R.string.UnknownError)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString("UnknownError", R.string.UnknownError)).show(); } else { - BulletinFactory.of(this).createSimpleBulletin(R.raw.error, LocaleController.getString("UnknownError", R.string.UnknownError)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString("UnknownError", R.string.UnknownError)).show(); } }); }); break; } case OPTION_RESTRICT: { - getMessagesController().deleteParticipantFromChat(currentChat.id, getMessagesController().getInputPeer(selectedObject.messageOwner.from_id)); + if (selectedParticipant != null) { + TLRPC.User user = getMessagesController().getUser(DialogObject.getPeerDialogId(selectedParticipant.peer)); + if (selectedParticipant.banned_rights == null) { + selectedParticipant.banned_rights = new TLRPC.TL_chatBannedRights(); + } + selectedParticipant.banned_rights.send_plain = true; + selectedParticipant.banned_rights.send_messages = true; + selectedParticipant.banned_rights.send_media = true; + selectedParticipant.banned_rights.send_stickers = true; + selectedParticipant.banned_rights.send_gifs = true; + selectedParticipant.banned_rights.send_games = true; + selectedParticipant.banned_rights.send_inline = true; + selectedParticipant.banned_rights.send_polls = true; + selectedParticipant.banned_rights.send_photos = true; + selectedParticipant.banned_rights.send_videos = true; + selectedParticipant.banned_rights.send_roundvideos = true; + selectedParticipant.banned_rights.send_audios = true; + selectedParticipant.banned_rights.send_voices = true; + selectedParticipant.banned_rights.send_docs = true; + getMessagesController().setParticipantBannedRole(currentChat.id, user, null, selectedParticipant.banned_rights, true, getFragmentForAlert(1), () -> { + BulletinFactory.of(this).createSimpleBulletin(R.raw.ic_ban, AndroidUtilities.replaceTags(LocaleController.formatString(R.string.RestrictedParticipantSending, UserObject.getFirstName(user)))).show(false); + reloadLastMessages(); + }); + } + break; + } + case OPTION_BAN: { + getMessagesController().deleteParticipantFromChat(currentChat.id, getMessagesController().getInputPeer(selectedObject.messageOwner.from_id), false, false, () -> { + reloadLastMessages(); + }); if (currentChat != null && selectedObject.messageOwner.from_id instanceof TLRPC.TL_peerUser && BulletinFactory.canShowBulletin(this)) { TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.from_id.user_id); if (user != null) { @@ -1850,6 +2311,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } selectedObject = null; + selectedParticipant = null; } private int getMessageType(MessageObject messageObject) { @@ -1937,8 +2399,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio admins.add(0, antispamParticipant); } } - if (visibleDialog instanceof AdminLogFilterAlert) { - ((AdminLogFilterAlert) visibleDialog).setCurrentAdmins(admins); + if (visibleDialog instanceof AdminLogFilterAlert2) { + ((AdminLogFilterAlert2) visibleDialog).setCurrentAdmins(admins); } } })); @@ -2009,9 +2471,9 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio int totalItemCount = chatAdapter.getItemCount(); int checkLoadCount; if (scroll) { - checkLoadCount = 25; + checkLoadCount = 4; } else { - checkLoadCount = 5; + checkLoadCount = 1; } if (firstVisibleItem <= checkLoadCount && !loading && !endReached) { loadMessages(false); @@ -2021,7 +2483,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private void moveScrollToLastMessage() { if (chatListView != null && !messages.isEmpty()) { - chatLayoutManager.scrollToPositionWithOffset(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + chatLayoutManager.scrollToPositionWithOffset(filteredMessages.size() - 1, -100000 - chatListView.getPaddingTop()); } } @@ -2083,7 +2545,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (viewBottom > height) { viewBottom = viewTop + height; } - messageCell.setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - AndroidUtilities.dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); + messageCell.setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); MessageObject messageObject = messageCell.getMessageObject(); if (roundVideoContainer != null && messageObject.isRoundVideo() && MediaController.getInstance().isPlayingMessage(messageObject)) { @@ -2201,6 +2663,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio public void onResume() { super.onResume(); + activityResumeTime = System.currentTimeMillis(); if (contentView != null) { contentView.onResume(); } @@ -2263,10 +2726,10 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setTitle(getString("AppName", R.string.AppName)); + builder.setPositiveButton(getString("OK", R.string.OK), null); if (message.type == MessageObject.TYPE_VIDEO) { - builder.setMessage(LocaleController.getString("NoPlayerInstalled", R.string.NoPlayerInstalled)); + builder.setMessage(getString("NoPlayerInstalled", R.string.NoPlayerInstalled)); } else { builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type)); } @@ -2298,24 +2761,24 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio Browser.openUrl(getParentActivity(), url, true); } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("OpenUrlTitle", R.string.OpenUrlTitle)); + builder.setTitle(getString("OpenUrlTitle", R.string.OpenUrlTitle)); builder.setMessage(LocaleController.formatString("OpenUrlAlert2", R.string.OpenUrlAlert2, url)); - builder.setPositiveButton(LocaleController.getString("Open", R.string.Open), (dialogInterface, i) -> Browser.openUrl(getParentActivity(), url, true)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(getString("Open", R.string.Open), (dialogInterface, i) -> Browser.openUrl(getParentActivity(), url, true)); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } } - private void removeMessageObject(MessageObject messageObject) { - int index = messages.indexOf(messageObject); - if (index == -1) { - return; - } - messages.remove(index); - if (chatAdapter != null) { - chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + messages.size() - index - 1); - } - } +// private void removeMessageObject(MessageObject messageObject) { +// int index = messages.indexOf(messageObject); +// if (index == -1) { +// return; +// } +// messages.remove(index); +// if (chatAdapter != null) { +// chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + messages.size() - index - 1); +// } +// } public class ChatActivityAdapter extends RecyclerView.Adapter { @@ -2327,18 +2790,26 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio public ChatActivityAdapter(Context context) { mContext = context; + setHasStableIds(true); } + private final ArrayList oldStableIds = new ArrayList<>(); + private final ArrayList stableIds = new ArrayList<>(); + public void updateRows() { + updateRows(true); + } + + public void updateRows(boolean animated) { rowCount = 0; - if (!messages.isEmpty()) { + if (!filteredMessages.isEmpty()) { if (!endReached) { loadingUpRow = rowCount++; } else { loadingUpRow = -1; } messagesStartRow = rowCount; - rowCount += messages.size(); + rowCount += filteredMessages.size(); messagesEndRow = rowCount; } else { loadingUpRow = -1; @@ -2353,8 +2824,20 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public long getItemId(int i) { - return RecyclerListView.NO_ID; + public long getItemId(int position) { + if (position >= messagesStartRow && position < messagesEndRow) { + return filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1).stableId; + } else if (position == loadingUpRow) { + return 2; + } + return 5; + } + + public MessageObject getMessageObject(int position) { + if (position >= messagesStartRow && position < messagesEndRow) { + return filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1); + } + return null; } @Override @@ -2370,6 +2853,23 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + @Override + public boolean shouldShowTopicButton() { + return ChatObject.isForum(currentChat); + } + + @Override + public void didPressTopicButton(ChatMessageCell cell) { + MessageObject message = cell.getMessageObject(); + if (message != null) { + Bundle args = new Bundle(); + args.putLong("chat_id", -message.getDialogId()); + ChatActivity chatActivity = new ChatActivity(args); + ForumUtilities.applyTopic(chatActivity, MessagesStorage.TopicKey.of(message.getDialogId(), MessageObject.getTopicId(currentAccount, message.messageOwner, true))); + presentFragment(chatActivity); + } + } + @Override public boolean canDrawOutboundsContent() { return true; @@ -2390,7 +2890,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio MediaController.getInstance().setVoiceMessagesPlaylist(null, false); return result; } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(messages, messageObject, 0); + return MediaController.getInstance().setPlaylist(filteredMessages, messageObject, 0); } return false; } @@ -2492,7 +2992,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (url instanceof URLSpanMono) { ((URLSpanMono) url).copyToClipboard(); if (AndroidUtilities.shouldShowClipboardToast()) { - Toast.makeText(getParentActivity(), LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); + Toast.makeText(getParentActivity(), getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); } } else if (url instanceof URLSpanUserMention) { long peerId = Utilities.parseLong(((URLSpanUserMention) url).getURL()); @@ -2521,7 +3021,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (longPress) { BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); builder.setTitle(urlFinal); - builder.setItems(new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { + builder.setItems(new CharSequence[]{getString("Open", R.string.Open), getString("Copy", R.string.Copy)}, (dialog, which) -> { if (which == 0) { Browser.openUrl(getParentActivity(), urlFinal, true); } else if (which == 1) { @@ -2561,7 +3061,21 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void didPressReplyMessage(ChatMessageCell cell, int id) { - + MessageObject messageObject = cell.getMessageObject(); + MessageObject reply = messageObject.replyMessageObject; + if (reply.getDialogId() == -currentChat.id) { + for (int i = 0; i < filteredMessages.size(); ++i) { + MessageObject msg = filteredMessages.get(i); + if (msg != null && msg.contentType != 1 && msg.getRealId() == reply.getRealId()) { + scrollToMessage(msg, true); + return; + } + } + } + Bundle args = new Bundle(); + args.putLong("chat_id", currentChat.id); + args.putInt("message_id", reply.getRealId()); + presentFragment(new ChatActivity(args)); } @Override @@ -2665,6 +3179,19 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } } + + @Override + public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { + MessageObject messageObject = cell.getMessageObject(); + if (expandedEvents.contains(messageObject.eventId)) { + expandedEvents.remove(messageObject.eventId); + } else { + expandedEvents.add(messageObject.eventId); + } + saveScrollPosition(true); + filterDeletedMessages(); + chatAdapter.notifyDataSetChanged(); + } }); chatMessageCell.setAllowAssistant(true); } else if (viewType == 1) { @@ -2762,7 +3289,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (finalInvite != null) { showInviteLinkBottomSheet(finalInvite, usersMap); } else { - BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("LinkHashExpired", R.string.LinkHashExpired)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, getString("LinkHashExpired", R.string.LinkHashExpired)).show(); } }); }); @@ -2770,7 +3297,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } else if (cachedInvite instanceof TLRPC.TL_messages_exportedChatInvite) { showInviteLinkBottomSheet((TLRPC.TL_messages_exportedChatInvite) cachedInvite, usersMap); } else { - BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("LinkHashExpired", R.string.LinkHashExpired)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, getString("LinkHashExpired", R.string.LinkHashExpired)).show(); } } @@ -2790,10 +3317,6 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } - @Override - public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { - - } }); } else if (viewType == 2) { view = new ChatUnreadCell(mContext, null); @@ -2808,9 +3331,9 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; - loadingCell.setProgressVisible(loadsCount > 1); + loadingCell.setProgressVisible(true); } else if (position >= messagesStartRow && position < messagesEndRow) { - MessageObject message = messages.get(messages.size() - (position - messagesStartRow) - 1); + MessageObject message = filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1); View view = holder.itemView; if (view instanceof ChatMessageCell) { @@ -2821,20 +3344,34 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio boolean pinnedBotton; boolean pinnedTop; if (!(message.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && nextType == holder.getItemViewType()) { - MessageObject nextMessage = messages.get(messages.size() - (position + 1 - messagesStartRow) - 1); + MessageObject nextMessage = filteredMessages.get(filteredMessages.size() - (position + 1 - messagesStartRow) - 1); pinnedBotton = nextMessage.isOutOwner() == message.isOutOwner() && (nextMessage.getFromChatId() == message.getFromChatId()) && Math.abs(nextMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; + if (pinnedBotton) { + long topicId = message.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, message.messageOwner, true) : message.replyToForumTopic.id; + long prevTopicId = nextMessage.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, nextMessage.messageOwner, true) : nextMessage.replyToForumTopic.id; + if (topicId != prevTopicId) { + pinnedBotton = false; + } + } } else { pinnedBotton = false; } if (prevType == holder.getItemViewType()) { - MessageObject prevMessage = messages.get(messages.size() - (position - messagesStartRow)); + MessageObject prevMessage = filteredMessages.get(filteredMessages.size() - (position - messagesStartRow)); pinnedTop = !(prevMessage.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && prevMessage.isOutOwner() == message.isOutOwner() && (prevMessage.getFromChatId() == message.getFromChatId()) && Math.abs(prevMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; + if (pinnedTop) { + long topicId = message.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, message.messageOwner, true) : message.replyToForumTopic.id; + long prevTopicId = prevMessage.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, prevMessage.messageOwner, true) : prevMessage.replyToForumTopic.id; + if (topicId != prevTopicId) { + pinnedTop = false; + } + } } else { pinnedTop = false; } messageCell.setMessageObject(message, null, pinnedBotton, pinnedTop); messageCell.setHighlighted(false); - messageCell.setHighlightedText(null); + messageCell.setHighlightedText(searchQuery); } else if (view instanceof ChatActionCell) { ChatActionCell actionCell = (ChatActionCell) view; actionCell.setMessageObject(message); @@ -2846,7 +3383,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public int getItemViewType(int position) { if (position >= messagesStartRow && position < messagesEndRow) { - return messages.get(messages.size() - (position - messagesStartRow) - 1).contentType; + return filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1).contentType; } return 4; } @@ -2870,7 +3407,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } if (holder.itemView instanceof ChatMessageCell) { - ((ChatMessageCell) view).setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - AndroidUtilities.dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); + ((ChatMessageCell) view).setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); } else if (holder.itemView instanceof ChatActionCell) { if (actionBar != null && contentView != null) { ((ChatActionCell) view).setVisiblePart(view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getBackgroundSizeY()); @@ -2893,11 +3430,11 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } public void updateRowWithMessageObject(MessageObject messageObject) { - int index = messages.indexOf(messageObject); + int index = filteredMessages.indexOf(messageObject); if (index == -1) { return; } - notifyItemChanged(messagesStartRow + messages.size() - index - 1); + notifyItemChanged(messagesStartRow + filteredMessages.size() - index - 1); } @Override @@ -2912,7 +3449,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemChanged(int position) { - updateRows(); + updateRows(false); try { super.notifyItemChanged(position); } catch (Exception e) { @@ -2922,7 +3459,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemRangeChanged(int positionStart, int itemCount) { - updateRows(); + updateRows(false); try { super.notifyItemRangeChanged(positionStart, itemCount); } catch (Exception e) { @@ -2932,7 +3469,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemInserted(int position) { - updateRows(); + updateRows(false); try { super.notifyItemInserted(position); } catch (Exception e) { @@ -2942,7 +3479,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemMoved(int fromPosition, int toPosition) { - updateRows(); + updateRows(false); try { super.notifyItemMoved(fromPosition, toPosition); } catch (Exception e) { @@ -2952,7 +3489,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemRangeInserted(int positionStart, int itemCount) { - updateRows(); + updateRows(false); try { super.notifyItemRangeInserted(positionStart, itemCount); } catch (Exception e) { @@ -2962,7 +3499,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemRemoved(int position) { - updateRows(); + updateRows(false); try { super.notifyItemRemoved(position); } catch (Exception e) { @@ -2972,7 +3509,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void notifyItemRangeRemoved(int positionStart, int itemCount) { - updateRows(); + updateRows(false); try { super.notifyItemRangeRemoved(positionStart, itemCount); } catch (Exception e) { @@ -2994,7 +3531,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void linkRevoked(TLRPC.TL_chatInviteExported invite) { TLRPC.TL_channelAdminLogEvent event = new TLRPC.TL_channelAdminLogEvent(); - int size = messages.size(); + int size = filteredMessages.size(); invite.revoked = true; TLRPC.TL_channelAdminLogEventActionExportedInviteRevoke revokeAction = new TLRPC.TL_channelAdminLogEventActionExportedInviteRevoke(); revokeAction.invite = invite; @@ -3005,7 +3542,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (messageObject.contentType < 0) { return; } - int addCount = messages.size() - size; + filterDeletedMessages(); + int addCount = filteredMessages.size() - size; if (addCount > 0) { chatListItemAnimator.setShouldAnimateEnterFromBottom(true); chatAdapter.notifyItemRangeInserted(chatAdapter.messagesEndRow, addCount); @@ -3016,7 +3554,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio @Override public void onLinkDeleted(TLRPC.TL_chatInviteExported invite) { - int size = messages.size(); + int size = filteredMessages.size(); int messagesEndRow = chatAdapter.messagesEndRow; TLRPC.TL_channelAdminLogEvent event = new TLRPC.TL_channelAdminLogEvent(); TLRPC.TL_channelAdminLogEventActionExportedInviteDelete deleteAction = new TLRPC.TL_channelAdminLogEventActionExportedInviteDelete(); @@ -3028,7 +3566,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (messageObject.contentType < 0) { return; } - int addCount = messages.size() - size; + filterDeletedMessages(); + int addCount = filteredMessages.size() - size; if (addCount > 0) { chatListItemAnimator.setShouldAnimateEnterFromBottom(true); chatAdapter.notifyItemRangeInserted(chatAdapter.messagesEndRow, addCount); @@ -3051,6 +3590,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (messageObject.contentType < 0) { return; } + filterDeletedMessages(); chatAdapter.notifyDataSetChanged(); moveScrollToLastMessage(); } @@ -3272,4 +3812,431 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio return themeDescriptions; } + + public void scrollToMessage(MessageObject object, boolean select) { + wasManualScroll = true; + int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; + int scrollFromIndex = 0; + if (filteredMessages.size() > 0) { + int end = chatLayoutManager.findLastVisibleItemPosition(); + for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { + if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { + MessageObject messageObject = filteredMessages.get(i - chatAdapter.messagesStartRow); + if (messageObject.contentType == 1 || messageObject.getRealId() == 0 || messageObject.isSponsored()) { + continue; + } + scrollFromIndex = i - chatAdapter.messagesStartRow; + boolean scrollDown = messageObject.getRealId() < object.getRealId(); + scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + break; + } + } + } + + chatScrollHelper.setScrollDirection(scrollDirection); + if (object != null) { + int index = filteredMessages.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 = object.getRealId(); + } + +// chatAdapter.updateRowsSafe(); + int position = chatAdapter.messagesStartRow + filteredMessages.indexOf(object); + + updateVisibleRows(); + boolean found = false; + int offsetY = 0; + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject != null && messageObject.getRealId() == object.getRealId()) { + found = true; + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + offsetY = scrollOffsetForQuote(messageObject); + } + } else if (view instanceof ChatActionCell) { + ChatActionCell cell = (ChatActionCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject != null && messageObject.getRealId() == object.getRealId()) { + found = true; + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + } + + if (found) { + int yOffset = getScrollOffsetForMessage(view.getHeight()) - offsetY; + int scrollY = (int) (view.getTop() - /*chatListViewPaddingTop - */yOffset); + int maxScrollOffset = chatListView.computeVerticalScrollRange() - chatListView.computeVerticalScrollOffset() - chatListView.computeVerticalScrollExtent(); + if (maxScrollOffset < 0) { + maxScrollOffset = 0; + } + if (scrollY > maxScrollOffset) { + scrollY = maxScrollOffset; + } + if (scrollY != 0) { +// scrollByTouch = false; + chatListView.smoothScrollBy(0, scrollY); + chatListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); + } + break; + } + } + if (!found) { + int yOffset = getScrollOffsetForMessage(object); + chatScrollHelperCallback.scrollTo = object; + chatScrollHelperCallback.lastBottom = false; + chatScrollHelperCallback.lastItemOffset = yOffset; +// chatScrollHelperCallback.lastPadding = (int) chatListViewPaddingTop; + chatScrollHelper.setScrollDirection(scrollDirection); + chatScrollHelper.scrollToPosition(chatScrollHelperCallback.position = position, chatScrollHelperCallback.offset = yOffset, chatScrollHelperCallback.bottom = false, true); +// canShowPagedownButton = true; +// updatePagedownButtonVisibility(true); + } + } + } +// returnToMessageId = fromMessageId; +// returnToLoadIndex = loadIndex; +// needSelectFromMessageId = select; + } + + private boolean wasManualScroll; + private MessageObject scrollToMessage; + public int highlightMessageId = Integer.MAX_VALUE; + public boolean showNoQuoteAlert; + public String highlightMessageQuote; + public int highlightMessageQuoteOffset = -1; + private int scrollToMessagePosition = -10000; + private Runnable unselectRunnable; + + private void startMessageUnselect() { + if (unselectRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(unselectRunnable); + } + unselectRunnable = () -> { + highlightMessageId = Integer.MAX_VALUE; + highlightMessageQuote = null; + highlightMessageQuoteOffset = -1; + showNoQuoteAlert = false; + updateVisibleRows(); + unselectRunnable = null; + }; + AndroidUtilities.runOnUIThread(unselectRunnable, highlightMessageQuote != null ? 2500 : 1000); + } + + private void removeSelectedMessageHighlight() { + if (highlightMessageQuote != null) { + return; + } + if (unselectRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(unselectRunnable); + unselectRunnable = null; + } + highlightMessageId = Integer.MAX_VALUE; + highlightMessageQuote = null; + } + + private void updateVisibleRows() { + updateVisibleRows(false); + } + + private void updateVisibleRows(boolean suppressUpdateMessageObject) { + if (chatListView == null) { + return; + } + int lastVisibleItem = RecyclerView.NO_POSITION; + int top = 0; +// if (!wasManualScroll && unreadMessageObject != null) { +// int n = chatListView.getChildCount(); +// for (int i = 0; i < n; i++) { +// View child = chatListView.getChildAt(i); +// if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == unreadMessageObject) { +// int unreadMessageIndex = messages.indexOf(unreadMessageObject); +// if (unreadMessageIndex >= 0) { +// lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject); +// top = getScrollingOffsetForView(child); +// } +// break; +// } +// } +// } + int count = chatListView.getChildCount(); +// MessageObject editingMessageObject = chatActivityEnterView != null ? chatActivityEnterView.getEditingMessageObject() : null; +// long linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject == null) + continue; + + boolean disableSelection = false; + boolean selected = false; + if (actionBar.isActionModeShowed()) { + highlightMessageQuote = null; +// cell.setCheckBoxVisible(threadMessageObjects == null || !threadMessageObjects.contains(messageObject), true); +// int idx = messageObject.getDialogId() == dialog_id ? 0 : 1; +// if (selectedMessagesIds[idx].indexOfKey(messageObject.getId()) >= 0) { +// setCellSelectionBackground(messageObject, cell, idx, true); +// selected = true; +// } else { +// cell.setDrawSelectionBackground(false); +// cell.setChecked(false, false, true); +// } + disableSelection = true; + } else { + cell.setDrawSelectionBackground(false); + cell.setCheckBoxVisible(false, true); + cell.setChecked(false, false, true); + } + +// if ((!cell.getMessageObject().deleted || cell.linkedChatId != linkedChatId) && !suppressUpdateMessageObject) { +// cell.setIsUpdating(true); +// cell.linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; +// cell.setMessageObject(cell.getMessageObject(), cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop()); +// cell.setIsUpdating(false); +// } +// if (cell != scrimView) { +// cell.setCheckPressed(!disableSelection, disableSelection && selected); +// } + cell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageObject != null && messageObject.getRealId() == highlightMessageId); + if (highlightMessageId != Integer.MAX_VALUE) { + startMessageUnselect(); + } + if (cell.isHighlighted() && highlightMessageQuote != null) { + if (!cell.setHighlightedText(highlightMessageQuote, true, highlightMessageQuoteOffset) && showNoQuoteAlert) { + showNoQuoteFound(); + } + showNoQuoteAlert = false; + } else if (!TextUtils.isEmpty(searchQuery)) { + cell.setHighlightedText(searchQuery); + } else { + cell.setHighlightedText(null); + } + cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); + } else if (view instanceof ChatActionCell) { + ChatActionCell cell = (ChatActionCell) view; + if (!suppressUpdateMessageObject) { + cell.setMessageObject(cell.getMessageObject()); + } + cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); + } + } + if (lastVisibleItem != RecyclerView.NO_POSITION) { + chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top); + } + } + + public void showNoQuoteFound() { + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString(R.string.QuoteNotFound)).show(true); + } + + + private ChatMessageCell dummyMessageCell; + private int getScrollOffsetForMessage(MessageObject object) { + return getScrollOffsetForMessage(getHeightForMessage(object, !TextUtils.isEmpty(highlightMessageQuote))) - scrollOffsetForQuote(object); + } + private int getScrollOffsetForMessage(int messageHeight) { + return (int) Math.max(-dp(2), (chatListView.getMeasuredHeight() - /*blurredViewBottomOffset - chatListViewPaddingTop - */messageHeight) / 2); + } + + private int scrollOffsetForQuote(MessageObject object) { + if (TextUtils.isEmpty(highlightMessageQuote) || object == null) { + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + return 0; + } + + int offsetY; + CharSequence text; + ArrayList textLayoutBlocks; +// if (object.getGroupId() != 0) { +// MessageObject.GroupedMessages group = getGroup(object.getGroupId()); +// if (dummyMessageCell == null || dummyMessageCell.computedCaptionLayout == null || group == null || group.captionMessage == null) { +// if (dummyMessageCell != null) { +// dummyMessageCell.computedGroupCaptionY = 0; +// dummyMessageCell.computedCaptionLayout = null; +// } +// return 0; +// } +// offsetY = dummyMessageCell.computedGroupCaptionY; +// text = group.captionMessage.caption; +// textLayoutBlocks = dummyMessageCell.computedCaptionLayout.textLayoutBlocks; +// } else + if (!TextUtils.isEmpty(object.caption) && dummyMessageCell != null && dummyMessageCell.captionLayout != null) { + offsetY = (int) dummyMessageCell.captionY; + text = object.caption; + textLayoutBlocks = dummyMessageCell.captionLayout.textLayoutBlocks; + } else { + offsetY = 0; + text = object.messageText; + textLayoutBlocks = object.textLayoutBlocks; + if (dummyMessageCell != null && dummyMessageCell.linkPreviewAbove) { + offsetY += dummyMessageCell.linkPreviewHeight + dp(10); + } + } + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + if (textLayoutBlocks == null || text == null) { + return 0; + } + + int index = MessageObject.findQuoteStart(text.toString(), highlightMessageQuote, highlightMessageQuoteOffset); + if (index < 0) { + return 0; + } + + for (int i = 0; i < textLayoutBlocks.size(); ++i) { + MessageObject.TextLayoutBlock block = textLayoutBlocks.get(i); + StaticLayout layout = block.textLayout; + String layoutText = layout.getText().toString(); + if (index > block.charactersOffset) { + final float y; + if (index - block.charactersOffset > layoutText.length() - 1) { + y = offsetY + (int) (block.textYOffset + block.padTop + block.height); + } else { + y = offsetY + block.textYOffset + block.padTop + layout.getLineTop(layout.getLineForOffset(index - block.charactersOffset)); + } + if (y > AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)) { + return (int) (y - AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)); + } + return 0; + } + } + return 0; + } + + private int getHeightForMessage(MessageObject object, boolean withGroupCaption) { + if (getParentActivity() == null) { + return 0; + } + if (dummyMessageCell == null) { + dummyMessageCell = new ChatMessageCell(getParentActivity()); + } + dummyMessageCell.isChat = currentChat != null; + dummyMessageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; + return dummyMessageCell.computeHeight(object, null, withGroupCaption); + } + + public boolean isKeyboardVisible() { + return contentView.getKeyboardHeight() > dp(20); + } + + + private int scrollCallbackAnimationIndex; + + private final ChatScrollCallback chatScrollHelperCallback = new ChatScrollCallback(); + public class ChatScrollCallback extends RecyclerAnimationScrollHelper.AnimationCallback { + + private MessageObject scrollTo; + private int position = 0; + private boolean bottom = true; + private int offset = 0; + private int lastItemOffset; + private boolean lastBottom; + private int lastPadding; + + @Override + public void onStartAnimation() { + super.onStartAnimation(); + scrollCallbackAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollCallbackAnimationIndex, allowedNotificationsDuringChatListAnimations); +// if (pinchToZoomHelper.isInOverlayMode()) { +// pinchToZoomHelper.finishZoom(); +// } + } + + @Override + public void onEndAnimation() { + if (scrollTo != null) { +// chatAdapter.updateRowsSafe(); + int lastItemPosition = chatAdapter.messagesStartRow + filteredMessages.indexOf(scrollTo); + if (lastItemPosition >= 0) { + chatLayoutManager.scrollToPositionWithOffset(lastItemPosition, (int) (lastItemOffset + lastPadding/* - chatListViewPaddingTop*/), lastBottom); + } + } else { +// chatAdapter.updateRowsSafe(); + chatLayoutManager.scrollToPositionWithOffset(position, offset, bottom); + } + scrollTo = null; + checkTextureViewPosition = true; + // chatListView.getOnScrollListener().onScrolled(chatListView, 0, chatScrollHelper.getScrollDirection() == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN ? 1 : -1); + + updateVisibleRows(); + + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().onAnimationFinish(scrollCallbackAnimationIndex)); + } + + @Override + public void recycleView(View view) { + if (view instanceof ChatMessageCell) { + chatMessageCellsCache.add((ChatMessageCell) view); + } + } + } + + private long savedScrollEventId; + private int savedScrollPosition = -1; + private int savedScrollOffset; + public void saveScrollPosition(boolean fromTop) { + if (chatListView != null && chatLayoutManager != null && chatListView.getChildCount() > 0) { + View view = null; + int position = -1; + int top = fromTop ? Integer.MAX_VALUE : Integer.MIN_VALUE; + for (int i = 0; i < chatListView.getChildCount(); i++) { + View child = chatListView.getChildAt(i); + int childPosition = chatListView.getChildAdapterPosition(child); + if (childPosition >= 0 && (fromTop ? child.getTop() < top : child.getTop() > top)) { + view = child; + position = childPosition; + top = child.getTop(); + } + } + if (view != null) { + long eventId = 0; + if (view instanceof ChatMessageCell) { + eventId = ((ChatMessageCell) view).getMessageObject().eventId; + } else if (view instanceof ChatActionCell) { + eventId = ((ChatActionCell) view).getMessageObject().eventId; + } + savedScrollEventId = eventId; + savedScrollPosition = position; + savedScrollOffset = getScrollingOffsetForView(view); + } + } + } + + private int getScrollingOffsetForView(View v) { + return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); + } + + public void applyScrolledPosition() { + if (chatListView != null && chatLayoutManager != null && savedScrollPosition >= 0) { + int adaptedPosition = savedScrollPosition; + if (savedScrollEventId != 0) { + for (int i = 0; i < chatAdapter.getItemCount(); ++i) { + MessageObject msg = chatAdapter.getMessageObject(i); + if (msg != null && msg.eventId == savedScrollEventId) { + adaptedPosition = i; + break; + } + } + } + chatLayoutManager.scrollToPositionWithOffset(adaptedPosition, savedScrollOffset, true); + savedScrollPosition = -1; + savedScrollEventId = 0; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java index 5483884e1..663ffceae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java @@ -17,8 +17,10 @@ import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Shader; @@ -39,6 +41,7 @@ import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; @@ -50,16 +53,21 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.DocumentObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SvgHelper; import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ResultCallback; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; @@ -378,6 +386,13 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe contentView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 68)); listView.setOnItemClickListener((view, position) -> { if (view instanceof EmojiCell) { + if (position == packStickerRow) { + if (chatFull == null) return; + GroupStickersActivity fragment = new GroupStickersActivity(-dialogId); + fragment.setInfo(chatFull); + presentFragment(fragment); + return; + } long selectedEmojiId = 0; if (position == replyEmojiRow) { selectedEmojiId = selectedReplyEmoji; @@ -878,6 +893,9 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe protected int packEmojiRow; protected int packEmojiHintRow; + protected int packStickerRow; + protected int packStickerHintRow; + protected void updateRows() { rowsCount = 0; messagesPreviewRow = rowsCount++; @@ -926,6 +944,14 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe return 0; } + protected int getStickerPackStrRes() { + return 0; + } + + protected int getStickerPackInfoStrRes() { + return 0; + } + protected int getEmojiStatusInfoStrRes() { return R.string.ChannelEmojiStatusInfo; } @@ -1097,6 +1123,15 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe } else { emojiCell.setEmoji(0, false); } + } else if (position == packStickerRow) { + emojiCell.setText(LocaleController.getString(getStickerPackStrRes())); + emojiCell.setLockLevel(0); + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId); + if (chatFull != null && chatFull.stickerset != null) { + emojiCell.setEmoji(getEmojiSetThumb(chatFull.stickerset), false); + } else { + emojiCell.setEmoji(0, false); + } } break; case VIEW_TYPE_SHADOW: @@ -1112,6 +1147,8 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe infoCell.setText(LocaleController.getString(getEmojiStatusInfoStrRes())); } else if (position == packEmojiHintRow) { infoCell.setText(LocaleController.getString(getEmojiPackInfoStrRes())); + } else if (position == packStickerHintRow) { + infoCell.setText(LocaleController.getString(getStickerPackInfoStrRes())); } else if (position == removeProfileColorShadowRow) { infoCell.setText(""); infoCell.setFixedSize(12); @@ -1165,7 +1202,7 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe return VIEW_TYPE_COLOR_REPLY_GRID; } else if (position == profileColorGridRow) { return VIEW_TYPE_COLOR_PROFILE_GRID; - } else if (position == replyEmojiRow || position == profileEmojiRow || position == statusEmojiRow || position == packEmojiRow) { + } else if (position == replyEmojiRow || position == profileEmojiRow || position == statusEmojiRow || position == packEmojiRow || position == packStickerRow) { return VIEW_TYPE_BUTTON_EMOJI; } else if (position == wallpaperRow || position == removeProfileColorRow) { return VIEW_TYPE_BUTTON; @@ -1230,6 +1267,7 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe View emojiPicker = findChildAt(profileEmojiRow); View emojiStatusPicker = findChildAt(statusEmojiRow); View packEmojiPicker = findChildAt(packEmojiRow); + View packStatusPicker = findChildAt(packStickerRow); if (profilePreview instanceof ProfilePreview) { ((ProfilePreview) profilePreview).setColor(selectedProfileColor, animated); @@ -1259,6 +1297,14 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe ((EmojiCell) packEmojiPicker).setEmoji(0, false); } } + if (packStatusPicker instanceof EmojiCell) { + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId); + if (chatFull != null && chatFull.stickerset != null) { + ((EmojiCell) packStatusPicker).setEmoji(getEmojiSetThumb(chatFull.stickerset), false); + } else { + ((EmojiCell) packStatusPicker).setEmoji(0, false); + } + } updateRows(); } @@ -1277,6 +1323,20 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe return thumbDocumentId; } + private TLRPC.Document getEmojiSetThumb(TLRPC.StickerSet emojiSet) { + if (emojiSet == null) { + return null; + } + long thumbDocumentId = emojiSet.thumb_document_id; + if (thumbDocumentId == 0) { + TLRPC.TL_messages_stickerSet stickerSet = getMediaDataController().getGroupStickerSetById(emojiSet); + if (!stickerSet.documents.isEmpty()) { + return stickerSet.documents.get(0); + } + } + return null; + } + public View findChildAt(int position) { for (int i = 0; i < listView.getChildCount(); ++i) { View child = listView.getChildAt(i); @@ -1439,6 +1499,18 @@ public class ChannelColorActivity extends BaseFragment implements NotificationCe } } + public void setEmoji(TLRPC.Document document, boolean animated) { + if (document == null) { + imageDrawable.set((Drawable) null, animated); + if (offText == null) { + offText = new Text(LocaleController.getString(R.string.ChannelReplyIconOff), 16); + } + } else { + imageDrawable.set(document, animated); + offText = null; + } + } + public void updateColors() { textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java index 50ae26a72..fc3711fac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java @@ -92,6 +92,8 @@ import java.util.Locale; public class ChannelMonetizationLayout extends FrameLayout { + public static ChannelMonetizationLayout instance; + private final BaseFragment fragment; private final Theme.ResourcesProvider resourcesProvider; private final int currentAccount; @@ -144,7 +146,7 @@ public class ChannelMonetizationLayout extends FrameLayout { showLearnSheet(); }, resourcesProvider), true); balanceInfo = AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(MessagesController.getInstance(currentAccount).channelRevenueWithdrawalEnabled ? R.string.MonetizationBalanceInfo : R.string.MonetizationBalanceInfoNotAvailable), -1, REPLACING_TAG_TYPE_LINK_NBSP, () -> { - showLearnSheet(); + Browser.openUrl(getContext(), getString(R.string.MonetizationBalanceInfoLink)); }), true); setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); @@ -383,6 +385,7 @@ public class ChannelMonetizationLayout extends FrameLayout { balanceSubtitle.setText("~" + BillingController.getInstance().formatCurrency(amount, "USD")); } + private double usd_rate; private void initLevel() { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); if (chat != null) { @@ -427,23 +430,8 @@ public class ChannelMonetizationLayout extends FrameLayout { impressionsChart.useHourFormat = true; } - availableValue.crypto_amount = stats.available_balance; - availableValue.amount = (long) (availableValue.crypto_amount / 1_000_000_000.0 * stats.usd_rate * 100.0); - setBalance(availableValue.crypto_amount, availableValue.amount); - availableValue.currency = "USD"; - lastWithdrawalValue.crypto_amount = stats.current_balance; - lastWithdrawalValue.amount = (long) (lastWithdrawalValue.crypto_amount / 1_000_000_000.0 * stats.usd_rate * 100.0); - lastWithdrawalValue.currency = "USD"; - lifetimeValue.crypto_amount = stats.overall_revenue; - lifetimeValue.amount = (long) (lifetimeValue.crypto_amount / 1_000_000_000.0 * stats.usd_rate * 100.0); - lifetimeValue.currency = "USD"; - proceedsAvailable = true; - - balanceButton.setVisibility(stats.available_balance > 0 || BuildVars.DEBUG_PRIVATE_VERSION ? View.VISIBLE : View.GONE); - - if (listView != null && listView.adapter != null) { - listView.adapter.update(true); - } + usd_rate = stats.usd_rate; + setupBalances(stats.balances); progress.animate().alpha(0).setDuration(380).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).withEndAction(() -> { progress.setVisibility(View.GONE); @@ -453,13 +441,41 @@ public class ChannelMonetizationLayout extends FrameLayout { } }), null, null, 0, stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); } + public void setupBalances(TLRPC.TL_broadcastRevenueBalances balances) { + if (usd_rate == 0) { + return; + } + availableValue.crypto_amount = balances.available_balance; + availableValue.amount = (long) (availableValue.crypto_amount / 1_000_000_000.0 * usd_rate * 100.0); + setBalance(availableValue.crypto_amount, availableValue.amount); + availableValue.currency = "USD"; + lastWithdrawalValue.crypto_amount = balances.current_balance; + lastWithdrawalValue.amount = (long) (lastWithdrawalValue.crypto_amount / 1_000_000_000.0 * usd_rate * 100.0); + lastWithdrawalValue.currency = "USD"; + lifetimeValue.crypto_amount = balances.overall_revenue; + lifetimeValue.amount = (long) (lifetimeValue.crypto_amount / 1_000_000_000.0 * usd_rate * 100.0); + lifetimeValue.currency = "USD"; + proceedsAvailable = true; + balanceButton.setVisibility(balances.available_balance > 0 || BuildVars.DEBUG_PRIVATE_VERSION ? View.VISIBLE : View.GONE); + + if (listView != null && listView.adapter != null) { + listView.adapter.update(true); + } + } @Override protected void onAttachedToWindow() { + instance = this; super.onAttachedToWindow(); checkLearnSheet(); } + @Override + protected void onDetachedFromWindow() { + instance = null; + super.onDetachedFromWindow(); + } + private void checkLearnSheet() { if (isAttachedToWindow() && proceedsAvailable && MessagesController.getGlobalMainSettings().getBoolean("monetizationadshint", true)) { showLearnSheet(); @@ -553,14 +569,22 @@ public class ChannelMonetizationLayout extends FrameLayout { } } + public void reloadTransactions() { + if (loadingTransactions) return; + transactions.clear(); + transactionsTotalCount = 0; + loadingTransactions = false; + loadTransactions(); + } + private boolean loadingTransactions = false; private void loadTransactions() { if (loadingTransactions) return; if (transactions.size() >= transactionsTotalCount && transactionsTotalCount != 0) return; -// TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); -// if (chat == null || !chat.creator) { -// return; -// } + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (chat == null || !chat.creator) { + return; + } loadingTransactions = true; TL_stats.TL_getBroadcastRevenueTransactions req = new TL_stats.TL_getBroadcastRevenueTransactions(); @@ -620,7 +644,7 @@ public class ChannelMonetizationLayout extends FrameLayout { if (ChannelMonetizationLayout.tonString == null) { ChannelMonetizationLayout.tonString = new HashMap<>(); } - final int key = textPaint.getFontMetricsInt().bottom * (large ? 1 : -1) * (int) (100 * scale); + final int key = textPaint.getFontMetricsInt().bottom * (large ? 1 : -1) * (int) (100 * scale) - (int) (100 * translateY); SpannableString tonString = ChannelMonetizationLayout.tonString.get(key); if (tonString == null) { tonString = new SpannableString("T"); @@ -807,13 +831,13 @@ public class ChannelMonetizationLayout extends FrameLayout { SpannableStringBuilder value = new SpannableStringBuilder(); value.append(type < 0 ? "-" : "+"); + value.append("TON "); value.append(formatter.format((Math.abs(amount) / 1_000_000_000.0))); - value.append(" TON"); int index = TextUtils.indexOf(value, "."); if (index >= 0) { value.setSpan(new RelativeSizeSpan(1.15f), 0, index + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - valueText.setText(value); + valueText.setText(replaceTON(value, valueText.getPaint(), 1.1f, dp(.33f), false)); valueText.setTextColor(Theme.getColor(type < 0 ? Theme.key_text_RedBold : Theme.key_avatar_nameInMessageGreen, resourcesProvider)); setWillNotDraw(!(needDivider = divider)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index b1fea30d8..227940718 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -158,6 +158,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; +import org.telegram.messenger.PushListenerController; import org.telegram.messenger.R; import org.telegram.messenger.SecretChatHelper; import org.telegram.messenger.SendMessagesHelper; @@ -261,6 +262,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -905,6 +907,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean openImport; public float chatListViewPaddingTop; + public float paddingTopHeight; public int chatListViewPaddingVisibleOffset; private int contentPaddingTop; @@ -1023,8 +1026,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.pinnedInfoDidLoad, NotificationCenter.didSetNewWallpapper, NotificationCenter.savedMessagesDialogsUpdate, - NotificationCenter.didApplyNewTheme, - NotificationCenter.messageReceivedByServer + NotificationCenter.didApplyNewTheme +// NotificationCenter.messageReceivedByServer }; private final DialogInterface.OnCancelListener postponedScrollCancelListener = dialog -> { @@ -4501,7 +4504,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } c.translate(0, getMeasuredHeight() - blurredViewBottomOffset - transitionOffset); if (pullingDownDrawable == null) { - pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, themeDelegate); + pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, getTopicId(), themeDelegate); + if (nextChannels != null && !nextChannels.isEmpty()) { + pullingDownDrawable.updateDialog(nextChannels.get(0)); + } else if (isTopic) { + pullingDownDrawable.updateTopic(); + } else { + pullingDownDrawable.updateDialog(); + } pullingDownDrawable.onAttach(); } pullingDownDrawable.setWidth(getMeasuredWidth()); @@ -5532,6 +5542,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); chatListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); chatListViewPaddingTop = 0; + paddingTopHeight = 0; invalidateChatListViewTopPadding(); if (MessagesController.getGlobalMainSettings().getBoolean("view_animations", true)) { chatListItemAnimator = new ChatListItemAnimator(this, chatListView, themeDelegate) { @@ -5762,9 +5773,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!foundTopView) { scrolled = super.scrollVerticallyBy(dy, recycler, state); } - if (dy > 0 && scrolled == 0 && ChatObject.isChannel(currentChat) && chatMode != MODE_SAVED && !currentChat.megagroup && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && reportType < 0) { + if (dy > 0 && scrolled == 0 && (ChatObject.isChannel(currentChat) && !currentChat.megagroup || isTopic) && chatMode != MODE_SAVED && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && reportType < 0) { if (pullingDownOffset == 0 && pullingDownDrawable != null) { - pullingDownDrawable.updateDialog(); + if (nextChannels != null && !nextChannels.isEmpty()) { + pullingDownDrawable.updateDialog(nextChannels.get(0)); + } else if (isTopic) { + pullingDownDrawable.updateTopic(); + } else { + pullingDownDrawable.updateDialog(); + } } if (pullingDownBackAnimator != null) { pullingDownBackAnimator.removeAllListeners(); @@ -9040,7 +9057,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not tagSelector.setVisibility(View.VISIBLE); tagSelector.setHint(LocaleController.getString(tagSelector.getSelectedReactions().isEmpty() ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); contentView.addView(tagSelector, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0)); - tagSelector.setMessage(null, null); + tagSelector.setMessage(null, null, true); tagSelector.setTranslationY(-dp(12)); tagSelector.setScaleY(.4f); tagSelector.setScaleX(.4f); @@ -9686,25 +9703,42 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pullingDownDrawable == null) { return; } -// if (getParentLayout().fragmentsStack.size() > 1) { -// BaseFragment previousFragment = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2); -// if (previousFragment instanceof ChatActivity) { -// getParentLayout().fragmentsStack.remove(getParentLayout().fragmentsStack.size() - 2); -// } -// } - addToPulledDialogsMyself(); - addToPulledDialogs(pullingDownDrawable.nextChat, pullingDownDrawable.nextDialogId, pullingDownDrawable.dialogFolderId, pullingDownDrawable.dialogFilterId); - Bundle bundle = new Bundle(); - bundle.putLong("chat_id", pullingDownDrawable.getChatId()); - bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); - bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); - bundle.putBoolean("pulled", true); - SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); - sharedPreferences.edit().remove("diditem" + pullingDownDrawable.nextDialogId).apply(); - ChatActivity chatActivity = new ChatActivity(bundle); - chatActivity.setPullingDownTransition(true); - replacingChatActivity = true; - presentFragment(chatActivity, true); + if (isTopic) { + if (pullingDownDrawable.getTopic() != null) { + addToPulledTopicsMyself(); + addToPulledDialogs(currentChat, pullingDownDrawable.nextTopic, dialog_id, dialogFolderId, dialogFilterId); + Bundle bundle = new Bundle(); + bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); + bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); + bundle.putBoolean("pulled", true); + ChatActivity chatActivity = ForumUtilities.getChatActivityForTopic(ChatActivity.this, -dialog_id, pullingDownDrawable.getTopic(), 0, bundle); + chatActivity.setPullingDownTransition(true); + replacingChatActivity = true; + presentFragment(chatActivity, true); + } + } else { + addToPulledDialogsMyself(); + addToPulledDialogs(pullingDownDrawable.nextChat, null, pullingDownDrawable.nextDialogId, pullingDownDrawable.dialogFolderId, pullingDownDrawable.dialogFilterId); + Bundle bundle = new Bundle(); + bundle.putLong("chat_id", pullingDownDrawable.getChatId()); + bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); + bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); + bundle.putBoolean("pulled", true); + SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); + sharedPreferences.edit().remove("diditem" + pullingDownDrawable.nextDialogId).apply(); + ChatActivity chatActivity = new ChatActivity(bundle); + if (nextChannels != null && nextChannels.size() > 1) { + chatActivity.setNextChannels(new ArrayList<>(nextChannels.subList(1, nextChannels.size()))); + } + chatActivity.setPullingDownTransition(true); + replacingChatActivity = true; + presentFragment(chatActivity, true); + } + } + + private ArrayList nextChannels; + public void setNextChannels(ArrayList channels) { + nextChannels = channels; } private void addToPulledDialogsMyself() { @@ -9712,14 +9746,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); - BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, dialog_id, dialogFilterId, dialogFolderId); + BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, null, dialog_id, dialogFilterId, dialogFolderId); } - private void addToPulledDialogs(TLRPC.Chat chat, long dialogId, int folderId, int filterId) { + private void addToPulledDialogs(TLRPC.Chat chat, TLRPC.TL_forumTopic topic, long dialogId, int folderId, int filterId) { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); - BackButtonMenu.addToPulledDialogs(this, stackIndex, chat, null, dialogId, folderId, filterId); + BackButtonMenu.addToPulledDialogs(this, stackIndex, chat, null, topic, dialogId, folderId, filterId); + } + + private void addToPulledTopicsMyself() { + if (getParentLayout() == null) { + return; + } + int stackIndex = getParentLayout().getFragmentStack().indexOf(this); + BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, forumTopic, dialog_id, dialogFilterId, dialogFolderId); } private void setPullingDownTransition(boolean fromPullingDownTransition) { @@ -10478,7 +10520,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset() - AndroidUtilities.dp(4)); } float oldPadding = chatListViewPaddingTop; - chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH; + chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + (paddingTopHeight = topPanelViewH + pinnedViewH + pendingViewH); chatListViewPaddingTop += blurredViewTopOffset; chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; @@ -12031,7 +12073,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatAttachAlert.setMaxSelectedPhotos(1, false); chatAttachAlert.setOpenWithFrontFaceCamera(true); - chatAttachAlert.enableStickerMode(); + chatAttachAlert.enableStickerMode(null); chatAttachAlert.init(); chatAttachAlert.parentThemeDelegate = themeDelegate; if (visibleDialog != null) { @@ -15515,12 +15557,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject.SendAnimationData data = cell.getMessageObject().sendAnimationData; if (data != null) { canvas.save(); + final int actionBarBottom = actionBar.getVisibility() == VISIBLE ? (int) actionBar.getTranslationY() + actionBar.getMeasuredHeight() + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0) + (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) : 0; + canvas.clipRect(0, actionBarBottom + paddingTopHeight, getWidth(), getHeight()); ImageReceiver imageReceiver = cell.getPhotoImage(); - canvas.translate(data.currentX, data.currentY); + cell.getLocationInWindow(AndroidUtilities.pointTmp2); + int finalY = AndroidUtilities.pointTmp2[1]; + finalY -= cell.getTranslationY() * (1.0f - data.progress); + finalY += chatActivityEnterView.topViewVisible() * AndroidUtilities.dp(48); + canvas.translate(data.currentX, AndroidUtilities.lerp(data.y, finalY + imageReceiver.getCenterY(), data.progress)); canvas.scale(data.currentScale, data.currentScale); canvas.translate(-imageReceiver.getCenterX(), -imageReceiver.getCenterY()); cell.setTimeAlpha(data.timeAlpha); - animateSendingViews.get(a).draw(canvas); + cell.draw(canvas); canvas.restore(); } } @@ -18989,11 +19037,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); inputStickerSet.access_hash = set.access_hash; inputStickerSet.id = set.id; + + final boolean replacing = args.length > 4 ? (boolean) args[4] : false; + + if (visibleDialog instanceof StickersAlert) { + StickersAlert existingAlert = (StickersAlert) visibleDialog; + if (existingAlert.stickerSet != null && existingAlert.stickerSet.set != null && existingAlert.stickerSet.set.id == set.id) { + existingAlert.updateStickerSet(((TLRPC.TL_messages_stickerSet) args[1])); + if (args.length > 2 && args[2] instanceof TLRPC.Document) { + TLRPC.Document stickerDocument = (TLRPC.Document) args[2]; + if (args.length > 3 && args[3] instanceof String) { + stickerDocument.localThumbPath = (String) args[3]; + } + BulletinFactory.of(existingAlert.container, resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(replacing ? R.string.StickersStickerEditedInSetToast : R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(true); + } + return; + } + } + StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate); alert.setOnShowListener(dialog -> { if (args.length > 2 && args[2] instanceof TLRPC.Document) { TLRPC.Document stickerDocument = (TLRPC.Document) args[2]; - BulletinFactory.of((FrameLayout) alert.getContainerView(), resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(); + if (args.length > 3 && args[3] instanceof String) { + stickerDocument.localThumbPath = (String) args[3]; + } + BulletinFactory.of(alert.container, resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(replacing ? R.string.StickersStickerEditedInSetToast : R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(true); } }); showDialog(alert); @@ -19495,7 +19564,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode, 0, null, classGuid); } if (chatAdapter != null) { - chatAdapter.updateRowWithMessageObject(obj, false, false); + ChatMessageCell cell = null; + for (int i = 0; i < chatListView.getChildCount(); ++i) { + View child = chatListView.getChildAt(i); + if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == obj) { + cell = (ChatMessageCell) child; + break; + } + } + chatAdapter.updateRowWithMessageObject(obj, animateSendingViews.contains(cell), false); } if (chatLayoutManager != null) { if (mediaUpdated && chatLayoutManager.findFirstVisibleItemPosition() == 0) { @@ -21563,8 +21640,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int sponsoredMessagesPostsBetween; private boolean sponsoredMessagesAdded; + private Pattern sponsoredUrlPattern; private void addSponsoredMessages(boolean animated) { - if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium()) { + if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium() && getMessagesController().isSponsoredDisabled()) { return; } MessagesController.SponsoredMessagesInfo res = getMessagesController().getSponsoredMessages(dialog_id); @@ -21574,12 +21652,36 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int i = 0; i < res.messages.size(); i++) { MessageObject messageObject = res.messages.get(i); messageObject.resetLayout(); - long dialogId = MessageObject.getPeerId(messageObject.messageOwner.from_id); - int messageId = 0; - if (messageObject.sponsoredChannelPost != 0) { - messageId = messageObject.sponsoredChannelPost; + if (messageObject.sponsoredUrl != null) { + try { + if (sponsoredUrlPattern == null) { + sponsoredUrlPattern = Pattern.compile("https://t\\.me/(\\w+)(?:/(\\d+))?"); + } + Matcher matcher = sponsoredUrlPattern.matcher(messageObject.sponsoredUrl); + if (matcher.matches()) { + String username = matcher.group(1); + int postId = 0; + try { + postId = matcher.groupCount() >= 2 ? Integer.parseInt(matcher.group(2)) : 0; + } catch (Exception e2) { + FileLog.e(e2); + } + TLObject obj = getMessagesController().getUserOrChat(username); + long did; + if (obj instanceof TLRPC.User) { + did = ((TLRPC.User) obj).id; + } else if (obj instanceof TLRPC.Chat) { + did = -((TLRPC.Chat) obj).id; + } else { + continue; + } + if (postId < 0) continue; + getMessagesController().ensureMessagesLoaded(did, postId, null); + } + } catch (Exception e) { + FileLog.e(e); + } } - getMessagesController().ensureMessagesLoaded(dialogId, messageId, null); } sponsoredMessagesAdded = true; sponsoredMessagesPostsBetween = res.posts_between != null ? res.posts_between : 0; @@ -22791,7 +22893,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (editingMessageObject == obj) { hideFieldPanel(true); } - int index = chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : messages.indexOf(obj); + int index = chatAdapter != null && chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : messages.indexOf(obj); if (index != -1) { if (obj.scheduled) { scheduledMessagesCount--; @@ -22801,7 +22903,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updatedSelected = true; addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); } - MessageObject removed = chatAdapter.getMessages().remove(index); + MessageObject removed = chatAdapter != null && chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.remove(index) : messages.remove(index); if (chatAdapter != null) { if (chatAdapter.isFiltered) { int mindex = messages.indexOf(obj); @@ -22862,7 +22964,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (filteredMessagesByDays != null) { dayArr = filteredMessagesByDays.get(obj.dateKeyInt); if (dayArr != null) { - MessageObject mobj = chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; + MessageObject mobj = chatAdapter != null && chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; dayArr.remove(mobj); if (dayArr.isEmpty()) { filteredMessagesByDays.remove(obj.dateKeyInt); @@ -22914,7 +23016,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = chatAdapter.getMessages().indexOf(messageObject); if (index >= 0) { - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFrozen) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); } } @@ -22963,7 +23065,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } } - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFrozen) { int prevHintRow = chatAdapter.hintRow; int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; @@ -23300,6 +23402,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not CharSequence text; if (!results.solution_entities.isEmpty()) { text = new SpannableStringBuilder(results.solution); + text = Emoji.replaceEmoji(text, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(13), false); + text = MessageObject.replaceAnimatedEmoji(text, results.solution_entities, Theme.chat_msgBotButtonPaint.getFontMetricsInt()); MessageObject.addEntitiesToText(text, results.solution_entities, false, true, true, false); } else { text = results.solution; @@ -24884,7 +24988,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinnedText = 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; + String mess = poll.poll.question.text; if (mess.length() > 150) { mess = mess.substring(0, 150); } @@ -25332,7 +25436,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getMessagesController().getTranslateController().isDialogTranslatable(getDialogId()) && !getMessagesController().getTranslateController().isTranslateDialogHidden(getDialogId()) : !getMessagesController().premiumFeaturesBlocked() && preferences.getInt("dialog_show_translate_count" + did, 5) <= 0 ); - boolean showBizBot = getUserConfig().isPremium() && preferences.getLong("dialog_botid" + did, 0) != 0; + boolean showBizBot = currentEncryptedChat == null && getUserConfig().isPremium() && preferences.getLong("dialog_botid" + did, 0) != 0; if (showRestartTopic) { shownRestartTopic = true; } @@ -26279,6 +26383,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } CharSequence message = ChatActivityEnterView.applyMessageEntities(entities, resolvedChatLink.message, chatActivityEnterView.getEditField().getPaint().getFontMetricsInt()); + if (message != null && message.length() > 0 && message.charAt(0) == '@') { + message = TextUtils.concat(" ", message); + } chatActivityEnterView.setFieldText(message, true, true); @@ -26635,19 +26742,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages selectedGroup) { - createDeleteMessagesAlert(finalSelectedObject, selectedGroup, 1); + private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup) { + createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, false); } - private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant) { - createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, loadParticipant, false); - } - - private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant, boolean hideDimAfter) { + private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, boolean hideDimAfter) { if (finalSelectedObject == null && (selectedMessagesIds[0].size() + selectedMessagesIds[1].size()) == 0) { return; } - AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, (int) getTopicId(), chatMode, loadParticipant, () -> { + AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, (int) getTopicId(), chatMode, null, () -> { hideActionMode(); updatePinnedMessageView(true); }, hideDimAfter ? () -> dimBehindView(false) : null, themeDelegate); @@ -26964,9 +27067,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not try { TLRPC.Poll poll = ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll; StringBuilder pollText = new StringBuilder(); - pollText = new StringBuilder(poll.question).append("\n"); - for (TLRPC.TL_pollAnswer answer : poll.answers) - pollText.append("\n\uD83D\uDD18 ").append(answer.text); + pollText = new StringBuilder(poll.question.text).append("\n"); + for (TLRPC.PollAnswer answer : poll.answers) + pollText.append("\n\uD83D\uDD18 ").append(answer.text == null ? "" : answer.text.text); messageTextToTranslate = pollText.toString(); } catch (Exception e) { } @@ -27251,7 +27354,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_sticker); TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { - if (getMediaDataController().canAddStickerToFavorites() && MessageObject.isStickerHasSet(document)) { + if (getMediaDataController().canAddStickerToFavorites()) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); @@ -27286,7 +27389,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (type == 9) { TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { - if (MessageObject.isStickerHasSet(document)) { + if (getMediaDataController().canAddStickerToFavorites()) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); @@ -27469,7 +27572,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } boolean showMessageSeen = !isReactionsViewAvailable && !isInScheduleMode() && currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().chatReadMarkExpirePeriod) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count <= getMessagesController().chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell); boolean showPrivateMessageSeen = !isReactionsViewAvailable && currentChat == null && currentEncryptedChat == null && (currentUser != null && !UserObject.isUserSelf(currentUser) && !UserObject.isReplyUser(currentUser) && !UserObject.isAnonymous(currentUser) && !currentUser.bot && !UserObject.isService(currentUser.id)) && (userInfo == null || !userInfo.read_dates_private) && !isInScheduleMode() && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().pmReadDateExpirePeriod) && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell); - boolean showSponsorInfo = selectedObject != null && selectedObject.isSponsored() && (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredWebPage != null || selectedObject.sponsoredBotApp != null); + boolean showSponsorInfo = selectedObject != null && selectedObject.isSponsored() && (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith("https://" + getMessagesController().linkPrefix)); if (chatMode == MODE_SAVED) { showMessageSeen = false; } @@ -27953,7 +28056,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (selectedObject != null && selectedObject.isSponsored()) { - if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredWebPage != null) { + if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith("https://" + getMessagesController().linkPrefix)) { LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(LinearLayout.VERTICAL); @@ -27968,13 +28071,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ArrayList sections = new ArrayList<>(); - if (selectedObject.sponsoredWebPage != null) { + if (selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith(getMessagesController().linkPrefix)) { TextView textView = new TextView(getParentActivity()); textView.setTextColor(getThemedColor(Theme.key_chat_messageLinkIn)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); - Uri uri = Uri.parse(selectedObject.sponsoredWebPage.url); + Uri uri = Uri.parse(selectedObject.sponsoredUrl); textView.setText(Browser.replaceHostname(uri, IDN.toUnicode(uri.getHost(), IDN.ALLOW_UNASSIGNED))); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, selectedObject.sponsoredAdditionalInfo == null ? 6 : 0)); textView.setOnClickListener(e -> { @@ -27982,13 +28085,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } logSponsoredClicked(selectedObject); - Browser.openUrl(getContext(), selectedObject.sponsoredWebPage.url, true, false); + Browser.openUrl(getContext(), selectedObject.sponsoredUrl, true, false); }); textView.setOnLongClickListener(e -> { if (selectedObject == null) { return false; } - if (AndroidUtilities.addToClipboard(selectedObject.sponsoredWebPage.url)) { + if (AndroidUtilities.addToClipboard(selectedObject.sponsoredUrl)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getParentActivity()), themeDelegate).createCopyLinkBulletin().show(); } return true; @@ -28325,7 +28428,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (group != null) { messageWithReactions = group.findPrimaryMessageObject(); } - reactionsLayout.setMessage(messageWithReactions, chatInfo); + reactionsLayout.setMessage(messageWithReactions, chatInfo, true); reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { @@ -28349,7 +28452,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - boolean showNoForwards = noforwards && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED && chatMode != MODE_SAVED; + boolean showNoForwards = (getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards && currentUser != null && currentUser.bot) && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED && chatMode != MODE_SAVED; scrimPopupContainerLayout.addView(popupLayout, LayoutHelper.createLinearRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, 0, isReactionsAvailable ? 36 : 0, 0)); scrimPopupContainerLayout.setPopupWindowLayout(popupLayout); if (showNoForwards) { @@ -29254,7 +29357,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } preserveDim = true; - createDeleteMessagesAlert(selectedObject, selectedObjectGroup, 1,true); + createDeleteMessagesAlert(selectedObject, selectedObjectGroup, true); break; } case OPTION_FORWARD: { @@ -29891,8 +29994,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case OPTION_HIDE_SPONSORED_MESSAGE: { - MessageObject message = selectedObject; - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + hideAds(); break; } case OPTION_ABOUT_REVENUE_SHARING_ADS: { @@ -29971,6 +30073,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not BulletinFactory.of(ChatActivity.this) .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) .show(); + getMessagesController().disableAds(false); removeFromSponsored(message); removeMessageWithThanos(message); }, 200); @@ -29996,7 +30099,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case OPTION_REMOVE_ADS: { - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + hideAds(); break; } case OPTION_SPEED_PROMO: { @@ -30015,6 +30118,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not closeMenu(!preserveDim); } + private void hideAds() { + if (getUserConfig().isPremium()) { + BulletinFactory.of(ChatActivity.this) + .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) + .show(); + getMessagesController().disableAds(true); + removeFromSponsored(selectedObject); + removeMessageWithThanos(selectedObject); + } else { + showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + } + } + @Override public boolean didSelectDialogs(DialogsActivity fragment, ArrayList dids, CharSequence message, boolean param, TopicsFragment topicsFragment) { if ((messagePreviewParams == null && (!fragment.isQuote || replyingMessageObject == null) || fragment.isQuote && replyingMessageObject == null) && forwardingMessage == null && selectedMessagesIds[0].size() == 0 && selectedMessagesIds[1].size() == 0) { @@ -32642,31 +32758,28 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return object.currentX; } }; - Property param3 = new AnimationProperties.FloatProperty("p3") { - @Override - public void setValue(MessageObject.SendAnimationData object, float value) { - object.currentY = value; - if (fragmentView != null) { - fragmentView.invalidate(); - } - } - - @Override - public Float get(MessageObject.SendAnimationData object) { - return object.currentY; - } - }; AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(sendAnimationData, param1, scale, 1.0f), - ObjectAnimator.ofFloat(sendAnimationData, param3, sendAnimationData.y, position[1] + imageReceiver.getCenterY()) + ObjectAnimator.ofFloat(sendAnimationData, new AnimationProperties.FloatProperty("progress") { + @Override + public void setValue(MessageObject.SendAnimationData object, float value) { + object.progress = value; + if (fragmentView != null) { + fragmentView.invalidate(); + } + } + @Override + public Float get(MessageObject.SendAnimationData object) { + return object.progress; + } + }, 0, 1) ); - animatorSet.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); ObjectAnimator o = ObjectAnimator.ofFloat(sendAnimationData, param2, sendAnimationData.x, position[0] + imageReceiver.getCenterX()); - o.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); allAnimators.playTogether(o, animatorSet); - allAnimators.setDuration(ChatListItemAnimator.DEFAULT_DURATION); + allAnimators.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + allAnimators.setDuration(460); allAnimators.addListener(new AnimatorListenerAdapter() { @Override @@ -32998,6 +33111,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void notifyItemChanged(int position) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("notify item changed " + position); + } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { @@ -33659,8 +33775,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didPressSponsoredClose() { - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + public void didPressSponsoredClose(ChatMessageCell cell) { + selectedObject = cell.getMessageObject(); + hideAds(); } @Override @@ -33845,7 +33962,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void openProfile(TLRPC.User user, boolean expandPhoto) { - if (user != null && user.id != getUserConfig().getClientUserId()) { + if (user != null) { if (user.photo == null || user.photo instanceof TLRPC.TL_userProfilePhotoEmpty) { expandPhoto = false; } @@ -33887,7 +34004,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (avatarContainer != null && postId == 0) { avatarContainer.openProfile(false); } else { - scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, true, 0); + scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, false, 0); } } else if (currentChat == null || chat.id != currentChat.id || isThreadChat()) { Bundle args = new Bundle(); @@ -34247,7 +34364,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override - public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { + public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { if (showCount >= 0 || buttons.isEmpty()) { if (getParentActivity() == null) { return; @@ -34920,111 +35037,98 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not args.putBoolean("addContact", true); presentFragment(new ContactAddActivity(args)); } + } else if (type == ChatMessageCell.INSTANT_BUTTON_TYPE_STICKER_SET || type == ChatMessageCell.INSTANT_BUTTON_TYPE_EMOJI_SET) { + final boolean emoji = type == ChatMessageCell.INSTANT_BUTTON_TYPE_EMOJI_SET; + TLRPC.WebPage webPage = null; + if (webPage == null && messageObject.messageOwner != null && messageObject.messageOwner.media != null) { + webPage = messageObject.messageOwner.media.webpage; + } + if (webPage == null || webPage.url == null) return; + Pattern pattern = Pattern.compile("^https?\\:\\/\\/t\\.me\\/add(?:emoji|stickers)\\/(.+)$"); + Matcher m = pattern.matcher(webPage.url); + + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } + } + }; + + if (m.matches() && m.groupCount() > 1 && m.group(1) != null) { + String setname = m.group(1); + TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccount).getStickerSetByName(setname); + if (set == null) { + progressDialogCurrent.init(); + TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); + TLRPC.TL_inputStickerSetShortName input = new TLRPC.TL_inputStickerSetShortName(); + input.short_name = setname; + req.stickerset = input; + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + progressDialogCurrent.end(); + if (res instanceof TLRPC.TL_messages_stickerSet) { + MediaDataController.getInstance(currentAccount).putStickerSet((TLRPC.TL_messages_stickerSet) res, false); + + TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); + inputStickerSet.access_hash = ((TLRPC.TL_messages_stickerSet) res).set.access_hash; + inputStickerSet.id = ((TLRPC.TL_messages_stickerSet) res).set.id; + if (emoji) { + ArrayList inputSets = new ArrayList<>(1); + inputSets.add(inputStickerSet); + EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); + alert.setCalcMandatoryInsets(isKeyboardVisible()); + showDialog(alert); + } else { + StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate); + alert.setCalcMandatoryInsets(isKeyboardVisible()); + showDialog(alert); + } + } else { + BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.error, getString(emoji ? R.string.AddEmojiNotFound : R.string.AddStickersNotFound)).show(true); + } + })); + progressDialogCurrent.onCancel(() -> ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true)); + return; + } + } + Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, false, progressDialogCurrent); } else { if (messageObject.isSponsored()) { logSponsoredClicked(messageObject); Bundle args = new Bundle(); - if (messageObject.sponsoredBotApp != null) { - TLRPC.TL_messages_getBotApp getBotApp = new TLRPC.TL_messages_getBotApp(); - TLRPC.TL_inputBotAppShortName app = new TLRPC.TL_inputBotAppShortName(); - if (messageObject.messageOwner == null || messageObject.messageOwner.from_id == null) { - return; + if (messageObject.sponsoredUrl != null) { + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); } - TLRPC.User bot = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.from_id.user_id); - if (bot == null) { - return; - } - app.bot_id = MessagesController.getInstance(currentAccount).getInputUser(bot); - app.short_name = messageObject.sponsoredBotApp.short_name; - getBotApp.app = app; - ConnectionsManager.getInstance(currentAccount).sendRequest(getBotApp, (response1, error1) -> { -// if (progress != null) { -// progress.end(); -// } - if (error1 != null) { - BulletinFactory.of(ChatActivity.this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(true); - } else { - TLRPC.TL_messages_botApp botApp = (TLRPC.TL_messages_botApp) response1; - AndroidUtilities.runOnUIThread(() -> { -// dismissLoading.run(); - AtomicBoolean allowWrite = new AtomicBoolean(); - Runnable loadBotSheet = () -> { - BotWebViewSheet sheet = new BotWebViewSheet(getContext(), getResourceProvider()); - sheet.setParentActivity(getParentActivity()); - sheet.requestWebView(currentAccount, bot.id, bot.id, null, null, BotWebViewSheet.TYPE_WEB_VIEW_BOT_APP, 0, false, ChatActivity.this, botApp.app, allowWrite.get(), messageObject.botStartParam, bot); - showDialog(sheet); - if (botApp.inactive) { - sheet.showJustAddedBulletin(); - } - }; + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } - if (botApp.request_write_access) { - AlertsCreator.createBotLaunchAlert(ChatActivity.this, allowWrite, bot, loadBotSheet); - } else { - loadBotSheet.run(); - } - }); - } - }); - } else if (messageObject.sponsoredWebPage != null) { - Browser.openUrl(getContext(), messageObject.sponsoredWebPage.url, true, false); - } else if (messageObject.sponsoredChatInvite != null) { - final TLRPC.TL_messages_checkChatInvite req = new TLRPC.TL_messages_checkChatInvite(); - req.hash = messageObject.sponsoredChatInviteHash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (error == null) { - TLRPC.ChatInvite invite = (TLRPC.ChatInvite) response; - if (invite.chat != null && (!ChatObject.isLeftFromChat(invite.chat) || !invite.chat.kicked && (ChatObject.isPublic(invite.chat) || invite instanceof TLRPC.TL_chatInvitePeek || invite.chat.has_geo))) { - MessagesController.getInstance(currentAccount).putChat(invite.chat, false); - ArrayList chats = new ArrayList<>(); - chats.add(invite.chat); - MessagesStorage.getInstance(currentAccount).putUsersAndChats(null, chats, false, true); - args.putLong("chat_id", invite.chat.id); - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, ChatActivity.this)) { - ChatActivity fragment = new ChatActivity(args); - if (invite instanceof TLRPC.TL_chatInvitePeek) { - fragment.setChatInvite(invite); - } - presentFragment(fragment); - } - } else { - showDialog(new JoinGroupAlert(getContext(), messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this, themeDelegate, JoinGroupAlert.ORIGINATION_SPONSORED_CHAT)); + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - if (error.text.startsWith("FLOOD_WAIT")) { - builder.setMessage(LocaleController.getString("FloodWait", R.string.FloodWait)); - } else if (error.text.startsWith("INVITE_HASH_EXPIRED")) { - builder.setTitle(LocaleController.getString("ExpiredLink", R.string.ExpiredLink)); - builder.setMessage(LocaleController.getString("InviteExpired", R.string.InviteExpired)); - } else { - builder.setMessage(LocaleController.getString("JoinToGroupErrorNotExist", R.string.JoinToGroupErrorNotExist)); - } - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); } - }), ConnectionsManager.RequestFlagFailOnServerErrors); - } else { - long peerId = MessageObject.getPeerId(messageObject.messageOwner.from_id); - if (peerId == getDialogId() && messageObject.sponsoredChannelPost != 0) { - scrollToMessageId(messageObject.sponsoredChannelPost, 0, true, 0, false, 0); - } else { - if (peerId < 0) { - args.putLong("chat_id", -peerId); - } else { - args.putLong("user_id", peerId); - } - if (messageObject.sponsoredChannelPost != 0) { - args.putInt("message_id", messageObject.sponsoredChannelPost); - } - if (messageObject.botStartParam != null) { - args.putString("inline_query", messageObject.botStartParam); - } - if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { - presentFragment(new ChatActivity(args)); - } - } + }; + Browser.openUrl(getContext(), Uri.parse(messageObject.sponsoredUrl), true, false, false, progressDialogCurrent); } } else { TLRPC.WebPage webPage = messageObject.getStoryMentionWebpage(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index cb10718d9..f9b1bff34 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.LocaleController.getString; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -244,7 +246,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image req.id = new TLRPC.TL_inputPhotoEmpty(); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { avatarImage.setImageDrawable(avatarDrawable); - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); if (currentUser != null) { currentUser.photo = null; @@ -600,7 +602,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image linearLayout1.setOrientation(LinearLayout.VERTICAL); - actionBar.setTitle(LocaleController.getString("ChannelEdit", R.string.ChannelEdit)); + actionBar.setTitle(getString("ChannelEdit", R.string.ChannelEdit)); avatarContainer = new LinearLayout(context); avatarContainer.setOrientation(LinearLayout.VERTICAL); @@ -691,11 +693,11 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image nameTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, this, EditTextEmoji.STYLE_FRAGMENT, false); if (userId != 0) { - nameTextView.setHint(LocaleController.getString(R.string.BotName)); + nameTextView.setHint(getString(R.string.BotName)); } else if (isChannel) { - nameTextView.setHint(LocaleController.getString("EnterChannelName", R.string.EnterChannelName)); + nameTextView.setHint(getString("EnterChannelName", R.string.EnterChannelName)); } else { - nameTextView.setHint(LocaleController.getString("GroupName", R.string.GroupName)); + nameTextView.setHint(getString("GroupName", R.string.GroupName)); } nameTextView.setEnabled(currentChat != null || ChatObject.canChangeChatInfo(currentChat)); nameTextView.setFocusable(nameTextView.isEnabled()); @@ -749,7 +751,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image req.id = new TLRPC.TL_inputPhotoEmpty(); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { avatarImage.setImageDrawable(avatarDrawable); - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); if (currentUser != null) { currentUser.photo = null; @@ -798,7 +800,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image inputFilters = new InputFilter[1]; inputFilters[0] = new InputFilter.LengthFilter(255); descriptionTextView.setFilters(inputFilters); - descriptionTextView.setHint(LocaleController.getString("DescriptionOptionalPlaceholder", R.string.DescriptionOptionalPlaceholder)); + descriptionTextView.setHint(getString("DescriptionOptionalPlaceholder", R.string.DescriptionOptionalPlaceholder)); descriptionTextView.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); descriptionTextView.setCursorSize(AndroidUtilities.dp(20)); descriptionTextView.setCursorWidth(1.5f); @@ -914,7 +916,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image HeaderCell headerCell = new HeaderCell(context, Theme.key_dialogTextBlue2, 23, 15, false); headerCell.setHeight(47); - headerCell.setText(LocaleController.getString("ChatHistory", R.string.ChatHistory)); + headerCell.setText(getString("ChatHistory", R.string.ChatHistory)); linearLayout.addView(headerCell); LinearLayout linearLayoutInviteContainer = new LinearLayout(context); @@ -928,12 +930,12 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image buttons[a].setTag(a); buttons[a].setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (a == 0) { - buttons[a].setTextAndValue(LocaleController.getString("ChatHistoryVisible", R.string.ChatHistoryVisible), LocaleController.getString("ChatHistoryVisibleInfo", R.string.ChatHistoryVisibleInfo), true, !historyHidden); + buttons[a].setTextAndValue(getString("ChatHistoryVisible", R.string.ChatHistoryVisible), getString("ChatHistoryVisibleInfo", R.string.ChatHistoryVisibleInfo), true, !historyHidden); } else { if (ChatObject.isChannel(currentChat)) { - buttons[a].setTextAndValue(LocaleController.getString("ChatHistoryHidden", R.string.ChatHistoryHidden), LocaleController.getString("ChatHistoryHiddenInfo", R.string.ChatHistoryHiddenInfo), false, historyHidden); + buttons[a].setTextAndValue(getString("ChatHistoryHidden", R.string.ChatHistoryHidden), getString("ChatHistoryHiddenInfo", R.string.ChatHistoryHiddenInfo), false, historyHidden); } else { - buttons[a].setTextAndValue(LocaleController.getString("ChatHistoryHidden", R.string.ChatHistoryHidden), LocaleController.getString("ChatHistoryHiddenInfo2", R.string.ChatHistoryHiddenInfo2), false, historyHidden); + buttons[a].setTextAndValue(getString("ChatHistoryHidden", R.string.ChatHistoryHidden), getString("ChatHistoryHiddenInfo2", R.string.ChatHistoryHiddenInfo2), false, historyHidden); } } linearLayoutInviteContainer.addView(buttons[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -968,7 +970,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (isChannel) { signCell = new TextCell(context, 23, false, true, null); signCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - signCell.setTextAndCheckAndIcon(LocaleController.getString("ChannelSignMessages", R.string.ChannelSignMessages), signMessages, R.drawable.msg_signed, false); + signCell.setTextAndCheckAndIcon(getString("ChannelSignMessages", R.string.ChannelSignMessages), signMessages, R.drawable.msg_signed, false); typeEditContainer.addView(signCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); signCell.setOnClickListener(v -> { signMessages = !signMessages; @@ -977,14 +979,14 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } else if (currentChat.creator) { forumsCell = new TextCell(context, 23, false, true, null); forumsCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - forumsCell.setTextAndCheckAndIcon(LocaleController.getString("ChannelTopics", R.string.ChannelTopics), forum, R.drawable.msg_topics, false); + forumsCell.setTextAndCheckAndIcon(getString("ChannelTopics", R.string.ChannelTopics), forum, R.drawable.msg_topics, false); forumsCell.getCheckBox().setIcon(canForum ? 0 : R.drawable.permission_locked); typeEditContainer.addView(forumsCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); forumsCell.setOnClickListener(v -> { if (!canForum) { CharSequence text; if (!(info == null || info.linked_chat_id == 0)) { - text = AndroidUtilities.replaceTags(LocaleController.getString("ChannelTopicsDiscussionForbidden", R.string.ChannelTopicsDiscussionForbidden)); + text = AndroidUtilities.replaceTags(getString("ChannelTopicsDiscussionForbidden", R.string.ChannelTopicsDiscussionForbidden)); } else { text = AndroidUtilities.replaceTags(LocaleController.formatPluralString("ChannelTopicsForbidden", getMessagesController().forumUpgradeParticipantsMin)); } @@ -1005,7 +1007,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image ActionBarMenu menu = actionBar.createMenu(); if (currentUser != null || ChatObject.canChangeChatInfo(currentChat) || signCell != null || historyCell != null) { doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56)); - doneButton.setContentDescription(LocaleController.getString("Done", R.string.Done)); + doneButton.setContentDescription(getString("Done", R.string.Done)); } if (locationCell != null || signCell != null || historyCell != null || typeCell != null || linkedCell != null || forumsCell != null) { @@ -1017,9 +1019,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image settingsSectionCell.setBackground(combinedDrawable); linearLayout1.addView(settingsSectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); if (forumsCell != null) { - settingsSectionCell.setText(LocaleController.getString("ForumToggleDescription", R.string.ForumToggleDescription)); + settingsSectionCell.setText(getString("ForumToggleDescription", R.string.ForumToggleDescription)); } else { - settingsSectionCell.setText(LocaleController.getString("ChannelSignMessagesInfo", R.string.ChannelSignMessagesInfo)); + settingsSectionCell.setText(getString("ChannelSignMessagesInfo", R.string.ChannelSignMessagesInfo)); } } @@ -1103,7 +1105,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (ChatObject.isBoostSupported(currentChat)) { statsAndBoosts = new TextCell(context); - statsAndBoosts.setTextAndIcon(LocaleController.getString("StatisticsAndBoosts", R.string.StatisticsAndBoosts), R.drawable.msg_stats, true); + statsAndBoosts.setTextAndIcon(getString(R.string.StatisticsAndBoosts), R.drawable.msg_stats, true); statsAndBoosts.setBackground(Theme.getSelectorDrawable(false)); statsAndBoosts.setOnClickListener(v -> { presentFragment(StatisticActivity.create(currentChat, false)); @@ -1129,31 +1131,11 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (isChannel || currentChat.gigagroup) { infoContainer.addView(blockCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } - if (!isChannel && info != null && info.can_set_stickers) { - stickersContainer = new FrameLayout(context); - stickersContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - linearLayout1.addView(stickersContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - stickersCell = new TextCell(context); - stickersCell.setBackground(Theme.getSelectorDrawable(false)); - stickersCell.setOnClickListener(v -> presentFragment(new ChannelAdminLogActivity(currentChat))); - stickersCell.setPrioritizeTitleOverValue(true); - stickersContainer.addView(stickersCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - stickersCell.setOnClickListener(v -> { - GroupStickersActivity groupStickersActivity = new GroupStickersActivity(currentChat.id); - groupStickersActivity.setInfo(info); - presentFragment(groupStickersActivity); - }); - if (statsAndBoosts != null) { - infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } - } else { - if (statsAndBoosts != null) { - infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } - if (logCell != null) { - infoContainer.addView(logCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } + if (statsAndBoosts != null) { + infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + if (logCell != null) { + infoContainer.addView(logCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } } @@ -1172,19 +1154,19 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image editIntroCell = new TextCell(context); editIntroCell.setBackground(Theme.getSelectorDrawable(false)); - editIntroCell.setTextAndIcon(LocaleController.getString(R.string.BotEditIntro), R.drawable.msg_log, true); + editIntroCell.setTextAndIcon(getString(R.string.BotEditIntro), R.drawable.msg_log, true); infoContainer.addView(editIntroCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); editIntroCell.setOnClickListener(v -> Browser.openUrl(v.getContext(), "https://t.me/BotFather?start=" + getActiveUsername(currentUser) + "-intro")); editCommandsCell = new TextCell(context); editCommandsCell.setBackground(Theme.getSelectorDrawable(false)); - editCommandsCell.setTextAndIcon(LocaleController.getString(R.string.BotEditCommands), R.drawable.msg_media, true); + editCommandsCell.setTextAndIcon(getString(R.string.BotEditCommands), R.drawable.msg_media, true); infoContainer.addView(editCommandsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); editCommandsCell.setOnClickListener(v -> Browser.openUrl(v.getContext(), "https://t.me/BotFather?start=" + getActiveUsername(currentUser) + "-commands")); changeBotSettingsCell = new TextCell(context); changeBotSettingsCell.setBackground(Theme.getSelectorDrawable(false)); - changeBotSettingsCell.setTextAndIcon(LocaleController.getString(R.string.BotChangeSettings), R.drawable.msg_bot, true); + changeBotSettingsCell.setTextAndIcon(getString(R.string.BotChangeSettings), R.drawable.msg_bot, true); infoContainer.addView(changeBotSettingsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); changeBotSettingsCell.setOnClickListener(v -> Browser.openUrl(v.getContext(), "https://t.me/BotFather?start=" + getActiveUsername(currentUser))); } @@ -1199,15 +1181,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image infoSectionCell = new ShadowSectionCell(context); linearLayout1.addView(infoSectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } - - if (!isChannel && info != null && info.can_set_stickers) { - stickersInfoCell = new TextInfoPrivacyCell(context); - stickersInfoCell.setText(LocaleController.getString(R.string.GroupStickersInfo)); - linearLayout1.addView(stickersInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } } else { botInfoCell = new TextInfoPrivacyCell(context); - String str = LocaleController.getString(R.string.BotManageInfo); + String str = getString(R.string.BotManageInfo); SpannableString span = SpannableString.valueOf(str); int index = str.indexOf("@BotFather"); if (index != -1) { @@ -1238,11 +1214,11 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image deleteCell.setTextColor(Theme.getColor(Theme.key_text_RedRegular)); deleteCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (currentUser != null) { - deleteCell.setText(LocaleController.getString(R.string.DeleteBot), false); + deleteCell.setText(getString(R.string.DeleteBot), false); } else if (isChannel) { - deleteCell.setText(LocaleController.getString("ChannelDelete", R.string.ChannelDelete), false); + deleteCell.setText(getString("ChannelDelete", R.string.ChannelDelete), false); } else { - deleteCell.setText(LocaleController.getString("DeleteAndExitButton", R.string.DeleteAndExitButton), false); + deleteCell.setText(getString("DeleteAndExitButton", R.string.DeleteAndExitButton), false); } deleteContainer.addView(deleteCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); deleteCell.setOnClickListener(v -> AlertsCreator.createClearOrDeleteDialogAlert(ChatEditActivity.this, false, true, false, currentChat, null, false, true, false, (param) -> { @@ -1296,9 +1272,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } } - publicLinkCell.setTextAndValueAndIcon(LocaleController.getString(R.string.BotPublicLinks), LocaleController.formatString(R.string.BotPublicLinksCount, usernamesActive, currentUser.usernames.size()), R.drawable.msg_link2, true); + publicLinkCell.setTextAndValueAndIcon(getString(R.string.BotPublicLinks), LocaleController.formatString(R.string.BotPublicLinksCount, usernamesActive, currentUser.usernames.size()), R.drawable.msg_link2, true); } else { - publicLinkCell.setTextAndValueAndIcon(LocaleController.getString(R.string.BotPublicLink), "t.me/" + currentUser.username, R.drawable.msg_link2, true); + publicLinkCell.setTextAndValueAndIcon(getString(R.string.BotPublicLink), "t.me/" + currentUser.username, R.drawable.msg_link2, true); } } @@ -1342,9 +1318,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (setAvatarCell != null) { if (hasPhoto || imageUpdater.isUploadingImage()) { - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); } else { - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); } if (cameraDrawable == null) { cameraDrawable = new RLottieDrawable(R.raw.camera_outline, "" + R.raw.camera_outline, AndroidUtilities.dp(50), AndroidUtilities.dp(50), false, null); @@ -1477,7 +1453,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image showAvatarProgress(false, true); } else { avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, currentUser != null ? currentUser : currentChat); - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); if (cameraDrawable == null) { cameraDrawable = new RLottieDrawable(R.raw.camera_outline, "" + R.raw.camera_outline, AndroidUtilities.dp(50), AndroidUtilities.dp(50), false, null); } @@ -1503,10 +1479,10 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (nameTextView != null && !currentUser.first_name.equals(nameTextView.getText().toString()) || descriptionTextView != null && !about.equals(descriptionTextView.getText().toString())) { showDialog(new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)) - .setMessage(LocaleController.getString(R.string.BotSettingsChangedAlert)) - .setPositiveButton(LocaleController.getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()) - .setNegativeButton(LocaleController.getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()) + .setTitle(getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)) + .setMessage(getString(R.string.BotSettingsChangedAlert)) + .setPositiveButton(getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()) + .setNegativeButton(getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()) .create()); return false; } @@ -1519,14 +1495,14 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image descriptionTextView != null && !about.equals(descriptionTextView.getText().toString()) || signMessages != currentChat.signatures || forum != currentChat.forum) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)); + builder.setTitle(getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)); if (isChannel) { - builder.setMessage(LocaleController.getString("ChannelSettingsChangedAlert", R.string.ChannelSettingsChangedAlert)); + builder.setMessage(getString("ChannelSettingsChangedAlert", R.string.ChannelSettingsChangedAlert)); } else { - builder.setMessage(LocaleController.getString("GroupSettingsChangedAlert", R.string.GroupSettingsChangedAlert)); + builder.setMessage(getString("GroupSettingsChangedAlert", R.string.GroupSettingsChangedAlert)); } - builder.setPositiveButton(LocaleController.getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()); - builder.setNegativeButton(LocaleController.getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()); + builder.setPositiveButton(getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()); + builder.setNegativeButton(getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()); showDialog(builder.create()); return false; } @@ -1778,7 +1754,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (logCell != null) { - logCell.setVisibility(!currentChat.megagroup || currentChat.gigagroup || info != null && info.participants_count > 200 ? View.VISIBLE : View.GONE); + logCell.setVisibility(ChatObject.isChannel(currentChat) ? View.VISIBLE : View.GONE); } if (linkedCell != null) { @@ -1787,7 +1763,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } else { linkedCell.setVisibility(View.VISIBLE); if (info.linked_chat_id == 0) { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("Discussion", R.string.Discussion), LocaleController.getString("DiscussionInfoShort", R.string.DiscussionInfoShort), R.drawable.msg_discuss, true); + linkedCell.setTextAndValueAndIcon(getString("Discussion", R.string.Discussion), getString("DiscussionInfoShort", R.string.DiscussionInfoShort), R.drawable.msg_discuss, true); } else { TLRPC.Chat chat = getMessagesController().getChat(info.linked_chat_id); if (chat == null) { @@ -1796,15 +1772,15 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image String username; if (isChannel) { if (TextUtils.isEmpty(username = ChatObject.getPublicUsername(chat))) { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("Discussion", R.string.Discussion), chat.title, R.drawable.msg_discuss,true); + linkedCell.setTextAndValueAndIcon(getString("Discussion", R.string.Discussion), chat.title, R.drawable.msg_discuss,true); } else { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("Discussion", R.string.Discussion), "@" + username, R.drawable.msg_discuss,true); + linkedCell.setTextAndValueAndIcon(getString("Discussion", R.string.Discussion), "@" + username, R.drawable.msg_discuss,true); } } else { if (TextUtils.isEmpty(username = ChatObject.getPublicUsername(chat))) { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("LinkedChannel", R.string.LinkedChannel), chat.title, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + linkedCell.setTextAndValueAndIcon(getString("LinkedChannel", R.string.LinkedChannel), chat.title, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } else { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("LinkedChannel", R.string.LinkedChannel), "@" + username, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + linkedCell.setTextAndValueAndIcon(getString("LinkedChannel", R.string.LinkedChannel), "@" + username, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } } } @@ -1817,9 +1793,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image locationCell.setVisibility(View.VISIBLE); if (info.location instanceof TLRPC.TL_channelLocation) { TLRPC.TL_channelLocation location = (TLRPC.TL_channelLocation) info.location; - locationCell.setTextAndValue(LocaleController.getString("AttachLocation", R.string.AttachLocation), location.address, animated, true); + locationCell.setTextAndValue(getString("AttachLocation", R.string.AttachLocation), location.address, animated, true); } else { - locationCell.setTextAndValue(LocaleController.getString("AttachLocation", R.string.AttachLocation), "Unknown address", animated, true); + locationCell.setTextAndValue(getString("AttachLocation", R.string.AttachLocation), "Unknown address", animated, true); } } else { locationCell.setVisibility(View.GONE); @@ -1830,30 +1806,30 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (info != null && info.location instanceof TLRPC.TL_channelLocation) { String link; if (isPrivate) { - link = LocaleController.getString("TypeLocationGroupEdit", R.string.TypeLocationGroupEdit); + link = getString("TypeLocationGroupEdit", R.string.TypeLocationGroupEdit); } else { link = String.format("https://" + getMessagesController().linkPrefix + "/%s", ChatObject.getPublicUsername(currentChat)); } - typeCell.setTextAndValueAndIcon(LocaleController.getString("TypeLocationGroup", R.string.TypeLocationGroup), link, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + typeCell.setTextAndValueAndIcon(getString("TypeLocationGroup", R.string.TypeLocationGroup), link, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } else { String type; boolean isRestricted = currentChat.noforwards; if (isChannel) { - type = isPrivate ? isRestricted ? LocaleController.getString("TypePrivateRestrictedForwards", R.string.TypePrivateRestrictedForwards) : LocaleController.getString("TypePrivate", R.string.TypePrivate) : LocaleController.getString("TypePublic", R.string.TypePublic); + type = isPrivate ? isRestricted ? getString("TypePrivateRestrictedForwards", R.string.TypePrivateRestrictedForwards) : getString("TypePrivate", R.string.TypePrivate) : getString("TypePublic", R.string.TypePublic); } else { - type = isPrivate ? isRestricted ? LocaleController.getString("TypePrivateGroupRestrictedForwards", R.string.TypePrivateGroupRestrictedForwards) : LocaleController.getString("TypePrivateGroup", R.string.TypePrivateGroup) : LocaleController.getString("TypePublicGroup", R.string.TypePublicGroup); + type = isPrivate ? isRestricted ? getString("TypePrivateGroupRestrictedForwards", R.string.TypePrivateGroupRestrictedForwards) : getString("TypePrivateGroup", R.string.TypePrivateGroup) : getString("TypePublicGroup", R.string.TypePublicGroup); } if (isChannel) { - typeCell.setTextAndValueAndIcon(LocaleController.getString("ChannelType", R.string.ChannelType), type, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + typeCell.setTextAndValueAndIcon(getString("ChannelType", R.string.ChannelType), type, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } else { - typeCell.setTextAndValueAndIcon(LocaleController.getString("GroupType", R.string.GroupType), type, R.drawable.msg_groups, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + typeCell.setTextAndValueAndIcon(getString("GroupType", R.string.GroupType), type, R.drawable.msg_groups, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } } } if (historyCell != null) { - String type = historyHidden && !forum ? LocaleController.getString("ChatHistoryHidden", R.string.ChatHistoryHidden) : LocaleController.getString("ChatHistoryVisible", R.string.ChatHistoryVisible); - historyCell.setTextAndValueAndIcon(LocaleController.getString("ChatHistoryShort", R.string.ChatHistoryShort), type, animated, R.drawable.msg_discuss, forumsCell != null); + String type = historyHidden && !forum ? getString("ChatHistoryHidden", R.string.ChatHistoryHidden) : getString("ChatHistoryVisible", R.string.ChatHistoryVisible); + historyCell.setTextAndValueAndIcon(getString("ChatHistoryShort", R.string.ChatHistoryShort), type, animated, R.drawable.msg_discuss, forumsCell != null); historyCell.setEnabled(!forum); updateHistoryShow(!forum && isPrivate && (info == null || info.linked_chat_id == 0) && !(info != null && info.location instanceof TLRPC.TL_channelLocation), animated); } @@ -1868,16 +1844,16 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image memberRequestsCell.setVisibility(info.requests_pending > 0 ? View.VISIBLE : View.GONE); } if (isChannel) { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelSubscribers", R.string.ChannelSubscribers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); - blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndValueAndIcon(getString("ChannelSubscribers", R.string.ChannelSubscribers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); + blockCell.setTextAndValueAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { if (ChatObject.isChannel(currentChat)) { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); + membersCell.setTextAndValueAndIcon(getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); } else { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants.participants.size()), R.drawable.msg_groups, memberRequestsCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndValueAndIcon(getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants.participants.size()), R.drawable.msg_groups, memberRequestsCell.getVisibility() == View.VISIBLE); } if (currentChat.gigagroup) { - blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + blockCell.setTextAndValueAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { int count = 0; if (currentChat.default_banned_rights != null) { @@ -1900,26 +1876,26 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } else { count = forum ? 14 : 13; } - blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelPermissions", R.string.ChannelPermissions), String.format("%d/%d", count, forum ? 14 : 13), animated, R.drawable.msg_permissions, true); + blockCell.setTextAndValueAndIcon(getString("ChannelPermissions", R.string.ChannelPermissions), String.format("%d/%d", count, forum ? 14 : 13), animated, R.drawable.msg_permissions, true); } if (memberRequestsCell != null) { - memberRequestsCell.setTextAndValueAndIcon(LocaleController.getString("MemberRequests", R.string.MemberRequests), String.format("%d", info.requests_pending), R.drawable.msg_requests, logCell != null && logCell.getVisibility() == View.VISIBLE); + memberRequestsCell.setTextAndValueAndIcon(getString("MemberRequests", R.string.MemberRequests), String.format("%d", info.requests_pending), R.drawable.msg_requests, logCell != null && logCell.getVisibility() == View.VISIBLE); } } - adminCell.setTextAndValueAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? info.admins_count : getAdminCount()), R.drawable.msg_admins, true); + adminCell.setTextAndValueAndIcon(getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? info.admins_count : getAdminCount()), R.drawable.msg_admins, true); } else { if (isChannel) { - membersCell.setTextAndIcon(LocaleController.getString("ChannelSubscribers", R.string.ChannelSubscribers), R.drawable.msg_groups, true); - blockCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndIcon(getString("ChannelSubscribers", R.string.ChannelSubscribers), R.drawable.msg_groups, true); + blockCell.setTextAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { - membersCell.setTextAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), R.drawable.msg_groups, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndIcon(getString("ChannelMembers", R.string.ChannelMembers), R.drawable.msg_groups, logCell != null && logCell.getVisibility() == View.VISIBLE); if (currentChat.gigagroup) { - blockCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + blockCell.setTextAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { - blockCell.setTextAndIcon(LocaleController.getString("ChannelPermissions", R.string.ChannelPermissions), R.drawable.msg_permissions, true); + blockCell.setTextAndIcon(getString("ChannelPermissions", R.string.ChannelPermissions), R.drawable.msg_permissions, true); } } - adminCell.setTextAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.msg_admins, true); + adminCell.setTextAndIcon(getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.msg_admins, true); } reactionsCell.setVisibility(ChatObject.canChangeChatInfo(currentChat) ? View.VISIBLE : View.GONE); updateReactionsCell(animated); @@ -1927,21 +1903,21 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image inviteLinksCell.setVisibility(View.GONE); } else { if (info.invitesCount > 0) { - inviteLinksCell.setTextAndValueAndIcon(LocaleController.getString("InviteLinks", R.string.InviteLinks), Integer.toString(info.invitesCount), R.drawable.msg_link2, true); + inviteLinksCell.setTextAndValueAndIcon(getString("InviteLinks", R.string.InviteLinks), Integer.toString(info.invitesCount), R.drawable.msg_link2, true); } else { - inviteLinksCell.setTextAndValueAndIcon(LocaleController.getString("InviteLinks", R.string.InviteLinks), "1", R.drawable.msg_link2, true); + inviteLinksCell.setTextAndValueAndIcon(getString("InviteLinks", R.string.InviteLinks), "1", R.drawable.msg_link2, true); } } } if (stickersCell != null && info != null) { - stickersCell.setTextAndValueAndIcon(LocaleController.getString(R.string.GroupStickers), info.stickerset != null ? info.stickerset.title : LocaleController.getString(R.string.Add), R.drawable.msg_sticker, false); + stickersCell.setTextAndValueAndIcon(getString(R.string.GroupStickers), info.stickerset != null ? info.stickerset.title : getString(R.string.Add), R.drawable.msg_sticker, false); } } public void updateColorCell() { if (colorCell != null) { - colorCell.set(currentChat, (historyCell != null && historyCell.getVisibility() == View.VISIBLE) || (signCell != null && signCell.getVisibility() == View.VISIBLE) || (forumsCell != null && forumsCell.getVisibility() == View.VISIBLE)); + colorCell.set(currentChat, (historyCell != null && historyCell.getVisibility() == View.VISIBLE) || (signCell != null && signCell.getVisibility() == View.VISIBLE) || (forumsCell != null && forumsCell.getVisibility() == View.VISIBLE) || ChatObject.isMegagroup(currentChat) && ChatObject.hasAdminRights(currentChat)); } } @@ -2022,7 +1998,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image boolean isChannelAndNotMegaGroup = ChatObject.isChannelAndNotMegaGroup(currentChat); String finalString; if (availableReactions == null || availableReactions instanceof TLRPC.TL_chatReactionsNone) { - finalString = LocaleController.getString("ReactionsOff", R.string.ReactionsOff); + finalString = getString("ReactionsOff", R.string.ReactionsOff); } else if (availableReactions instanceof TLRPC.TL_chatReactionsSome) { TLRPC.TL_chatReactionsSome someReactions = (TLRPC.TL_chatReactionsSome) availableReactions; int count = 0; @@ -2039,16 +2015,16 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } } if (isChannelAndNotMegaGroup) { - finalString = count == 0 ? LocaleController.getString("ReactionsOff", R.string.ReactionsOff) : String.valueOf(count); + finalString = count == 0 ? getString("ReactionsOff", R.string.ReactionsOff) : String.valueOf(count); } else { int reacts = Math.min(getMediaDataController().getEnabledReactionsList().size(), count); - finalString = reacts == 0 ? LocaleController.getString("ReactionsOff", R.string.ReactionsOff) : + finalString = reacts == 0 ? getString("ReactionsOff", R.string.ReactionsOff) : LocaleController.formatString("ReactionsCount", R.string.ReactionsCount, reacts, getMediaDataController().getEnabledReactionsList().size()); } } else { - finalString = LocaleController.getString("ReactionsAll", R.string.ReactionsAll); + finalString = getString("ReactionsAll", R.string.ReactionsAll); } - reactionsCell.setTextAndValueAndIcon(LocaleController.getString("Reactions", R.string.Reactions), finalString, animated, R.drawable.msg_reactions2, true); + reactionsCell.setTextAndValueAndIcon(getString("Reactions", R.string.Reactions), finalString, animated, R.drawable.msg_reactions2, true); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java index 77aa81792..45ee3f263 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java @@ -4,15 +4,19 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; @@ -29,9 +33,14 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CounterView; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.Forum.ForumUtilities; +import org.telegram.ui.Components.LetterDrawable; +import org.telegram.ui.Components.StaticLayoutEx; import java.util.ArrayList; @@ -56,8 +65,10 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC int layout1Width; int layout2Width; - ImageReceiver imageReceiver = new ImageReceiver(); + private final ImageReceiver imageReceiver; TLRPC.Chat nextChat; + TLRPC.TL_forumTopic nextTopic; + private long lastWidthTopicId = 0L; AnimatorSet showReleaseAnimator; @@ -74,26 +85,34 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC private final View fragmentView; public long lastShowingReleaseTime; + boolean recommendedChannel; boolean drawFolderBackground; + private final boolean isTopic; Runnable onAnimationFinishRunnable; public long nextDialogId; View parentView; + private boolean visibleCounterDrawable = true; CounterView.CounterDrawable counterDrawable = new CounterView.CounterDrawable(null, true, null); int params[] = new int[3]; private final int currentAccount; private final int folderId; private final int filterId; + private final long topicId; private final long currentDialog; private final Theme.ResourcesProvider resourcesProvider; + private AnimatedEmojiDrawable animatedEmojiDrawable; - public ChatPullingDownDrawable(int currentAccount, View fragmentView, long currentDialog, int folderId, int filterId, Theme.ResourcesProvider resourcesProvider) { + public ChatPullingDownDrawable(int currentAccount, View fragmentView, long currentDialog, int folderId, int filterId, long topicId, Theme.ResourcesProvider resourcesProvider) { this.fragmentView = fragmentView; this.currentAccount = currentAccount; this.currentDialog = currentDialog; this.folderId = folderId; this.filterId = filterId; + this.topicId = topicId; + this.isTopic = MessagesController.getInstance(currentAccount).isForum(currentDialog); this.resourcesProvider = resourcesProvider; + this.imageReceiver = new ImageReceiver(fragmentView); arrowPaint.setStrokeWidth(AndroidUtilities.dpf2(2.8f)); arrowPaint.setStrokeCap(Paint.Cap.ROUND); @@ -109,11 +128,37 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC xRefPaint.setColor(0xff000000); xRefPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } - updateDialog(); + public void updateDialog(TLRPC.Chat chat) { + if (chat == null) { + updateDialog(); + return; + } + + nextDialogId = -chat.id; + drawFolderBackground = params[0] == 1; + dialogFolderId = params[1]; + dialogFilterId = params[2]; + emptyStub = false; + nextChat = chat; + AvatarDrawable avatarDrawable = new AvatarDrawable(); + avatarDrawable.setInfo(currentAccount, nextChat); + imageReceiver.setImage(ImageLocation.getForChat(nextChat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, UserConfig.getInstance(0).getCurrentUser(), 0); + MessagesController.getInstance(currentAccount).ensureMessagesLoaded(-chat.id, 0, null); + + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).getDialog(-chat.id); + final int count = dialog == null ? 0 : dialog.unread_count; + counterDrawable.setCount(count, false); + visibleCounterDrawable = count > 0; + + recommendedChannel = true; + nextTopic = null; } public void updateDialog() { + recommendedChannel = false; + nextTopic = null; TLRPC.Dialog dialog = getNextUnreadDialog(currentDialog, folderId, filterId, true, params); if (dialog != null) { nextDialogId = dialog.id; @@ -123,13 +168,15 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC emptyStub = false; nextChat = MessagesController.getInstance(currentAccount).getChat(-dialog.id); if (nextChat == null) { - MessagesController.getInstance(currentAccount).getChat(dialog.id); + nextChat = MessagesController.getInstance(currentAccount).getChat(dialog.id); } AvatarDrawable avatarDrawable = new AvatarDrawable(); avatarDrawable.setInfo(currentAccount, nextChat); imageReceiver.setImage(ImageLocation.getForChat(nextChat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, UserConfig.getInstance(0).getCurrentUser(), 0); MessagesController.getInstance(currentAccount).ensureMessagesLoaded(dialog.id, 0, null); - counterDrawable.setCount(dialog.unread_count, false); + final int count = dialog.unread_count; + counterDrawable.setCount(count, false); + visibleCounterDrawable = count > 0; } else { nextChat = null; drawFolderBackground = false; @@ -137,28 +184,92 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC } } + public void updateTopic() { + recommendedChannel = false; + drawFolderBackground = false; + nextChat = null; + nextDialogId = 0; + imageReceiver.clearImage(); + + TLRPC.TL_forumTopic topic = getNextUnreadTopic(-currentDialog); + if (topic != null) { + emptyStub = false; + nextTopic = topic; + Drawable forumIcon; + if (topic.id == 1) { + if (parentView != null && animatedEmojiDrawable != null) { + animatedEmojiDrawable.removeView(parentView); + } + animatedEmojiDrawable = null; + forumIcon = ForumUtilities.createGeneralTopicDrawable(fragmentView.getContext(), 1f, getThemedColor(Theme.key_chat_inMenu), false); + imageReceiver.setImageBitmap(forumIcon); + } else if (topic.icon_emoji_id != 0) { + if (animatedEmojiDrawable == null || animatedEmojiDrawable.getDocumentId() != topic.icon_emoji_id) { + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.removeView(parentView); + } + animatedEmojiDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_FORUM_TOPIC_LARGE, currentAccount, topic.icon_emoji_id); + animatedEmojiDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_serviceText), PorterDuff.Mode.SRC_IN)); + } + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.addView(parentView); + } + imageReceiver.setImageBitmap((Bitmap) null); + } else { + if (parentView != null && animatedEmojiDrawable != null) { + animatedEmojiDrawable.removeView(parentView); + } + animatedEmojiDrawable = null; + forumIcon = ForumUtilities.createTopicDrawable(topic, false); + imageReceiver.setImageBitmap(forumIcon); + } + final int count = topic.unread_count; + counterDrawable.setCount(count, false); + visibleCounterDrawable = count > 0; + } else { + nextTopic = null; + emptyStub = true; + } + } + public void setWidth(int width) { - if (width != lastWidth) { + if (width != lastWidth || (isTopic && nextTopic != null && lastWidthTopicId != nextTopic.id)) { circleRadius = AndroidUtilities.dp(56) / 2f; lastWidth = width; - String nameStr = nextChat != null ? nextChat.title : LocaleController.getString("SwipeToGoNextChannelEnd", R.string.SwipeToGoNextChannelEnd); - chatNameWidth = (int) textPaint.measureText(nameStr); + CharSequence nameStr; + if (nextChat != null) { + nameStr = nextChat.title; + } else if (nextTopic != null) { + nameStr = nextTopic.title; + } else if (isTopic) { + String forumName = MessagesController.getInstance(currentAccount).getChat(-currentDialog).title; + nameStr = LocaleController.formatString(R.string.SwipeToGoNextTopicEnd, forumName); + } else { + nameStr = LocaleController.getString(R.string.SwipeToGoNextChannelEnd); + } + chatNameWidth = (int) textPaint.measureText(nameStr, 0, nameStr.length()); chatNameWidth = Math.min(chatNameWidth, lastWidth - AndroidUtilities.dp(60)); - chatNameLayout = new StaticLayout(nameStr, textPaint, chatNameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + chatNameLayout = StaticLayoutEx.createStaticLayout(nameStr, textPaint, chatNameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, chatNameWidth, 1); String str1 = null; String str2 = null; - if (drawFolderBackground && dialogFolderId != folderId && dialogFolderId != 0) { - str1 = LocaleController.getString("SwipeToGoNextArchive", R.string.SwipeToGoNextArchive); - str2 = LocaleController.getString("ReleaseToGoNextArchive", R.string.ReleaseToGoNextArchive); + if (recommendedChannel) { + str1 = LocaleController.getString(R.string.SwipeToGoNextRecommendedChannel); + str2 = LocaleController.getString(R.string.ReleaseToGoNextRecommendedChannel); + } else if (isTopic) { + str1 = LocaleController.getString(R.string.SwipeToGoNextUnreadTopic); + str2 = LocaleController.getString(R.string.ReleaseToGoNextUnreadTopic); + } else if (drawFolderBackground && dialogFolderId != folderId && dialogFolderId != 0) { + str1 = LocaleController.getString(R.string.SwipeToGoNextArchive); + str2 = LocaleController.getString(R.string.ReleaseToGoNextArchive); } else if (drawFolderBackground) { - str1 = LocaleController.getString("SwipeToGoNextFolder", R.string.SwipeToGoNextFolder); - str2 = LocaleController.getString("ReleaseToGoNextFolder", R.string.ReleaseToGoNextFolder); + str1 = LocaleController.getString(R.string.SwipeToGoNextFolder); + str2 = LocaleController.getString(R.string.ReleaseToGoNextFolder); } else { - str1 = LocaleController.getString("SwipeToGoNextChannel", R.string.SwipeToGoNextChannel); - str2 = LocaleController.getString("ReleaseToGoNextChannel", R.string.ReleaseToGoNextChannel); + str1 = LocaleController.getString(R.string.SwipeToGoNextChannel); + str2 = LocaleController.getString(R.string.ReleaseToGoNextChannel); } layout1Width = (int) textPaint2.measureText(str1); layout1Width = Math.min(layout1Width, lastWidth - AndroidUtilities.dp(60)); @@ -176,12 +287,20 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC imageReceiver.setRoundRadius((int) (AndroidUtilities.dp(40) / 2f)); counterDrawable.setSize(AndroidUtilities.dp(28), AndroidUtilities.dp(100)); + if (isTopic) { + lastWidthTopicId = nextTopic == null ? 0 : nextTopic.id; + } } } public void draw(Canvas canvas, View parent, float progress, float alpha) { - this.parentView = parent; + if (this.parentView != parent) { + this.parentView = parent; + if (animatedEmojiDrawable != null) { + animatedEmojiDrawable.addView(parent); + } + } counterDrawable.setParent(parent); int oldAlpha, oldAlpha1, oldAlpha2, oldAlpha3; float offset = AndroidUtilities.dp(110) * progress; @@ -287,12 +406,21 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC if (!emptyStub && size > 0) { float top = (-AndroidUtilities.dp(8) - AndroidUtilities.dp2(8) * progress - size) * (1f - swipeToReleaseProgress) + (-offset + AndroidUtilities.dp(4)) * swipeToReleaseProgress + bounceOffset; - imageReceiver.setRoundRadius((int) (size / 2f)); - imageReceiver.setImageCoords(cx - size / 2f, top, size, size); + ImageReceiver finalImageReceiver; + if (animatedEmojiDrawable != null && animatedEmojiDrawable.getImageReceiver() != null) { + finalImageReceiver = animatedEmojiDrawable.getImageReceiver(); + } else { + finalImageReceiver = imageReceiver; + } + finalImageReceiver.setRoundRadius((int) (size / 2f)); + finalImageReceiver.setImageCoords(cx - size / 2f, top, size, size); + if (isTopic && finalImageReceiver.getDrawable() != null && finalImageReceiver.getDrawable() instanceof CombinedDrawable && ((CombinedDrawable) finalImageReceiver.getDrawable()).getIcon() instanceof LetterDrawable) { + ((LetterDrawable) ((CombinedDrawable) finalImageReceiver.getDrawable()).getIcon()).scale = progress; + } - if (swipeToReleaseProgress > 0) { - canvas.saveLayerAlpha(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX() + imageReceiver.getImageWidth(), imageReceiver.getImageY() + imageReceiver.getImageHeight(), 255, Canvas.ALL_SAVE_FLAG); - imageReceiver.draw(canvas); + if (swipeToReleaseProgress > 0 && visibleCounterDrawable) { + canvas.saveLayerAlpha(finalImageReceiver.getImageX(), finalImageReceiver.getImageY(), finalImageReceiver.getImageX() + finalImageReceiver.getImageWidth(), finalImageReceiver.getImageY() + finalImageReceiver.getImageHeight(), 255, Canvas.ALL_SAVE_FLAG); + finalImageReceiver.draw(canvas); canvas.scale(swipeToReleaseProgress, swipeToReleaseProgress, cx + AndroidUtilities.dp(12) + counterDrawable.getCenterX(), top - AndroidUtilities.dp(6) + AndroidUtilities.dp(14)); canvas.translate(cx + AndroidUtilities.dp(12), top - AndroidUtilities.dp(6)); counterDrawable.updateBackgroundRect(); @@ -306,8 +434,7 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC counterDrawable.draw(canvas); canvas.restore(); } else { - - imageReceiver.draw(canvas); + finalImageReceiver.draw(canvas); } } @@ -476,12 +603,18 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC public void onAttach() { imageReceiver.onAttachedToWindow(); + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.addView(parentView); + } NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces); } public void onDetach() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateInterfaces); imageReceiver.onDetachedFromWindow(); + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.removeView(parentView); + } lastProgress = 0; lastHapticTime = 0; } @@ -491,7 +624,9 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC if (nextDialogId != 0) { TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(nextDialogId); if (dialog != null) { - counterDrawable.setCount(dialog.unread_count, true); + final int count = dialog.unread_count; + counterDrawable.setCount(count, true); + visibleCounterDrawable = count > 0; if (parentView != null) { parentView.invalidate(); } @@ -568,10 +703,28 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC return null; } + private TLRPC.TL_forumTopic getNextUnreadTopic(long currentDialogId) { + ArrayList topics = MessagesController.getInstance(currentAccount).getTopicsController().getTopics(currentDialogId); + TLRPC.TL_forumTopic nextUnreadTopic = null; + if (topics != null && topics.size() > 1) { + for (int i = 0; i < topics.size(); i++) { + TLRPC.TL_forumTopic topic = topics.get(i); + if (topic.id != topicId && !topic.hidden && topic.unread_count > 0 && (nextUnreadTopic == null || topic.topMessage.date > nextUnreadTopic.topMessage.date)) { + nextUnreadTopic = topic; + } + } + } + return nextUnreadTopic; + } + public long getChatId() { return nextChat.id; } + public TLRPC.TL_forumTopic getTopic() { + return nextTopic; + } + public void drawBottomPanel(Canvas canvas, int top, int bottom, int width) { if (showBottomPanel && progressToBottomPanel != 1f) { progressToBottomPanel += 16f / 150f; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index f7b2a5615..68fbd37ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -111,6 +111,7 @@ public class ChatRightsEditActivity extends BaseFragment { private TLRPC.TL_chatAdminRights myAdminRights; private TLRPC.TL_chatBannedRights bannedRights; private TLRPC.TL_chatBannedRights defaultBannedRights; + public boolean banning; private String currentBannedRights = ""; private String currentRank; private String initialRank; @@ -595,6 +596,7 @@ public class ChatRightsEditActivity extends BaseFragment { } finishFragment(); } else if (currentType == TYPE_BANNED) { + banning = true; bannedRights = new TLRPC.TL_chatBannedRights(); bannedRights.view_messages = true; bannedRights.send_media = true; @@ -2067,6 +2069,9 @@ public class ChatRightsEditActivity extends BaseFragment { bannedRights.send_photos = !enabled; bannedRights.send_videos = !enabled; bannedRights.send_stickers = !enabled; + bannedRights.send_gifs = !enabled; + bannedRights.send_games = !enabled; + bannedRights.send_inline = !enabled; bannedRights.send_audios = !enabled; bannedRights.send_docs = !enabled; bannedRights.send_voices = !enabled; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index a4450a507..b976fd411 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -449,7 +449,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } else if (type == TYPE_ADMIN) { if (ChatObject.isChannel(currentChat) && currentChat.megagroup && !currentChat.gigagroup && (info == null || info.participants_count <= 200 || !isChannel && info.can_set_stickers)) { - recentActionsRow = rowCount++; +// recentActionsRow = rowCount++; if (ChatObject.hasAdminRights(currentChat)) { antiSpamRow = rowCount++; antiSpamInfoRow = rowCount++; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java new file mode 100644 index 000000000..7433fd5b8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java @@ -0,0 +1,397 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; + +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.CheckBoxCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; + +public class AdminLogFilterAlert2 extends BottomSheetWithRecyclerListView { + + private UniversalAdapter adapter; + + private TLRPC.TL_channelAdminLogEventsFilter currentFilter = new TLRPC.TL_channelAdminLogEventsFilter(); + private ArrayList currentAdmins; + private LongSparseArray selectedAdmins; + private boolean isMegagroup; + + + private final ButtonWithCounterView actionButton; + private final SelectorBtnCell buttonContainer; + + public AdminLogFilterAlert2(BaseFragment fragment, TLRPC.TL_channelAdminLogEventsFilter filter, LongSparseArray admins, boolean megagroup) { + super(fragment, false, false); + topPadding = 0.6f; + fixNavigationBar(); + setSlidingActionBar(); + setShowHandle(true); + + if (filter != null) { + currentFilter.join = filter.join; + currentFilter.leave = filter.leave; + currentFilter.invite = filter.invite; + currentFilter.ban = filter.ban; + currentFilter.unban = filter.unban; + currentFilter.kick = filter.kick; + currentFilter.unkick = filter.unkick; + currentFilter.promote = filter.promote; + currentFilter.demote = filter.demote; + currentFilter.info = filter.info; + currentFilter.settings = filter.settings; + currentFilter.pinned = filter.pinned; + currentFilter.edit = filter.edit; + currentFilter.delete = filter.delete; + currentFilter.group_call = filter.group_call; + currentFilter.invites = filter.invites; + } else { + currentFilter.join = true; + currentFilter.leave = true; + currentFilter.invite = true; + currentFilter.ban = true; + currentFilter.unban = true; + currentFilter.kick = true; + currentFilter.unkick = true; + currentFilter.promote = true; + currentFilter.demote = true; + currentFilter.info = true; + currentFilter.settings = true; + currentFilter.pinned = true; + currentFilter.edit = true; + currentFilter.delete = true; + currentFilter.group_call = true; + currentFilter.invites = true; + } + if (admins != null) { + selectedAdmins = admins.clone(); + } + isMegagroup = megagroup; + adapter.update(false); + + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDelayAnimations(false); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDurations(350); + recyclerListView.setItemAnimator(itemAnimator); + recyclerListView.setOnItemClickListener((view, position, x, y) -> { + onClick(adapter.getItem(position - 1), view, x); + }); + + buttonContainer = new SelectorBtnCell(getContext(), resourcesProvider, null); + buttonContainer.setClickable(true); + buttonContainer.setOrientation(LinearLayout.VERTICAL); + buttonContainer.setPadding(dp(10), dp(10), dp(10), dp(10)); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + actionButton = new ButtonWithCounterView(getContext(), resourcesProvider); + actionButton.setText(getString(R.string.EventLogFilterApply), false); + actionButton.setOnClickListener(v -> { + if (currentFilter.join && + currentFilter.leave && + currentFilter.invite && + currentFilter.ban && + currentFilter.unban && + currentFilter.kick && + currentFilter.unkick && + currentFilter.promote && + currentFilter.demote && + currentFilter.info && + currentFilter.settings && + currentFilter.pinned && + currentFilter.edit && + currentFilter.delete && + currentFilter.group_call && + currentFilter.invites) { + currentFilter = null; + } + if (selectedAdmins != null && currentAdmins != null && selectedAdmins.size() >= currentAdmins.size()) { + selectedAdmins = null; + } + delegate.didSelectRights(currentFilter, selectedAdmins); + dismiss(); + }); + buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(68)); + } + + @Override + protected CharSequence getTitle() { + return getString(R.string.EventLog); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + return adapter = new UniversalAdapter(listView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider); + } + + private final static int FILTER_SECTION_MEMBERS = 2; + private final static int FILTER_NEW_ADMINS = 3; + private final static int FILTER_RESTRICTIONS = 4; + private final static int FILTER_NEW_MEMBERS = 5; + private final static int FILTER_MEMBERS_LEFT = 6; + private final static int FILTER_SECTION_SETTINGS = 7; + private final static int FILTER_INFO = 8; + private final static int FILTER_INVITES = 9; + private final static int FILTER_CALLS = 10; + private final static int FILTER_SECTION_MESSAGES = 11; + private final static int FILTER_DELETE = 12; + private final static int FILTER_EDIT = 13; + private final static int FILTER_PIN = 14; + private final static int BUTTON_ALL_ADMINS = 15; + + private boolean sectionMembersExpanded = false; + private boolean sectionSettingsExpanded = false; + private boolean sectionMessagesExpanded = false; + + private String getGroupCount(int a) { + switch (a) { + case 0: return ( + (currentFilter.promote || currentFilter.demote ? 1 : 0) + + (isMegagroup && (currentFilter.kick || currentFilter.ban || currentFilter.unkick || currentFilter.unban) ? 1 : 0) + + (currentFilter.invite || currentFilter.join ? 1 : 0) + + (currentFilter.leave ? 1 : 0) + + "/" + (isMegagroup ? 4 : 3) + ); + case 1: return ( + (currentFilter.info || currentFilter.settings ? 1 : 0) + + (currentFilter.invites ? 1 : 0) + + (currentFilter.group_call ? 1 : 0) + + "/3" + ); + case 2: + default: return ( + (currentFilter.delete ? 1 : 0) + + (currentFilter.edit ? 1 : 0) + + (currentFilter.pinned ? 1 : 0) + + "/3" + ); + } + } + + private View.OnClickListener getGroupClick(int a) { + return v -> { + saveScrollPosition(); + switch (a) { + case 0: + sectionMembersExpanded = !sectionMembersExpanded; + break; + case 1: + sectionSettingsExpanded = !sectionSettingsExpanded; + break; + case 2: + sectionMessagesExpanded = !sectionMessagesExpanded; + break; + } + adapter.update(true); + applyScrolledPosition(); + }; + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + if (currentFilter == null) return; + items.add(UItem.asHeader(getString(R.string.EventLogFilterByActions))); + items.add(UItem.asRoundGroupCheckbox(FILTER_SECTION_MEMBERS, getString(R.string.EventLogFilterSectionMembers), getGroupCount(0)).setChecked( + currentFilter.promote || currentFilter.demote || + isMegagroup && (currentFilter.kick || currentFilter.ban || currentFilter.unkick || currentFilter.unban) || + currentFilter.invite || currentFilter.join || + currentFilter.leave + ).setCollapsed(!sectionMembersExpanded).setClickCallback(getGroupClick(0))); + if (sectionMembersExpanded) { + items.add(UItem.asRoundCheckbox(FILTER_NEW_ADMINS, getString(R.string.EventLogFilterSectionAdmin)).pad().setChecked(currentFilter.promote || currentFilter.demote)); + if (isMegagroup) { + items.add(UItem.asRoundCheckbox(FILTER_RESTRICTIONS, getString(R.string.EventLogFilterNewRestrictions)).pad().setChecked(currentFilter.kick || currentFilter.ban || currentFilter.unkick || currentFilter.unban)); + } + items.add(UItem.asRoundCheckbox(FILTER_NEW_MEMBERS, getString(R.string.EventLogFilterNewMembers)).pad().setChecked(currentFilter.invite || currentFilter.join)); + items.add(UItem.asRoundCheckbox(FILTER_MEMBERS_LEFT, getString(R.string.EventLogFilterLeavingMembers2)).pad().setChecked(currentFilter.leave)); + } + items.add(UItem.asRoundGroupCheckbox(FILTER_SECTION_SETTINGS, getString(isMegagroup ? R.string.EventLogFilterSectionGroupSettings : R.string.EventLogFilterSectionChannelSettings), getGroupCount(1)).setChecked( + currentFilter.info || currentFilter.settings || + currentFilter.invites || + currentFilter.group_call + ).setCollapsed(!sectionSettingsExpanded).setClickCallback(getGroupClick(1))); + if (sectionSettingsExpanded) { + items.add(UItem.asRoundCheckbox(FILTER_INFO, getString(isMegagroup ? R.string.EventLogFilterGroupInfo : R.string.EventLogFilterChannelInfo)).pad().setChecked(currentFilter.info || currentFilter.settings)); + items.add(UItem.asRoundCheckbox(FILTER_INVITES, getString(R.string.EventLogFilterInvites)).pad().setChecked(currentFilter.invites)); + items.add(UItem.asRoundCheckbox(FILTER_CALLS, getString(R.string.EventLogFilterCalls)).pad().setChecked(currentFilter.group_call)); + } + items.add(UItem.asRoundGroupCheckbox(FILTER_SECTION_MESSAGES, getString(R.string.EventLogFilterSectionMessages), getGroupCount(2)).setChecked( + currentFilter.delete || currentFilter.edit || currentFilter.pinned + ).setCollapsed(!sectionMessagesExpanded).setClickCallback(getGroupClick(2))); + if (sectionMessagesExpanded) { + items.add(UItem.asRoundCheckbox(FILTER_DELETE, getString(R.string.EventLogFilterDeletedMessages)).pad().setChecked(currentFilter.delete)); + items.add(UItem.asRoundCheckbox(FILTER_EDIT, getString(R.string.EventLogFilterEditedMessages)).pad().setChecked(currentFilter.edit)); + items.add(UItem.asRoundCheckbox(FILTER_PIN, getString(R.string.EventLogFilterPinnedMessages)).pad().setChecked(currentFilter.pinned)); + } + items.add(UItem.asShadow(null)); + items.add(UItem.asHeader(getString(R.string.EventLogFilterByAdmins))); + items.add(UItem.asRoundCheckbox(BUTTON_ALL_ADMINS, getString(R.string.EventLogFilterByAdminsAll)).setChecked((selectedAdmins == null ? 0 : selectedAdmins.size()) >= (currentAdmins == null ? 0 : currentAdmins.size()))); + if (currentAdmins != null) { + for (int i = 0; i < currentAdmins.size(); ++i) { + TLRPC.ChannelParticipant admin = currentAdmins.get(i); + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + items.add(UItem.asUserCheckbox(-1 - i, user).pad().setChecked(selectedAdmins != null && selectedAdmins.containsKey(did))); + } + } + } + + public void onClick(UItem item, View view, float x) { + if (item == null) return; + if (item.viewType == UniversalAdapter.VIEW_TYPE_ROUND_GROUP_CHECKBOX || item.viewType == UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX) { + saveScrollPosition(); + final boolean clickedGroupExpand = item.viewType == UniversalAdapter.VIEW_TYPE_ROUND_GROUP_CHECKBOX && (LocaleController.isRTL ? x < view.getMeasuredWidth() - dp(60) : x > dp(60)); + CheckBoxCell cell = (CheckBoxCell) view; + if (!clickedGroupExpand) { + cell.setChecked(!cell.isChecked(), true); + } + switch (item.id) { + case FILTER_SECTION_MEMBERS: + if (clickedGroupExpand) { + sectionMembersExpanded = !sectionMembersExpanded; + } else { + currentFilter.promote = currentFilter.demote = currentFilter.invite = currentFilter.join = currentFilter.leave = cell.isChecked(); + if (isMegagroup) { + currentFilter.kick = currentFilter.ban = currentFilter.unkick = currentFilter.unban = cell.isChecked(); + } + } + break; + case FILTER_NEW_ADMINS: + currentFilter.promote = currentFilter.demote = cell.isChecked(); + break; + case FILTER_RESTRICTIONS: + currentFilter.kick = currentFilter.ban = currentFilter.unkick = currentFilter.unban = cell.isChecked(); + break; + case FILTER_NEW_MEMBERS: + currentFilter.invite = currentFilter.join = cell.isChecked(); + break; + case FILTER_MEMBERS_LEFT: + currentFilter.leave = cell.isChecked(); + break; + case FILTER_SECTION_SETTINGS: + if (clickedGroupExpand) { + sectionSettingsExpanded = !sectionSettingsExpanded; + } else { + currentFilter.info = currentFilter.settings = currentFilter.invites = currentFilter.group_call = cell.isChecked(); + } + break; + case FILTER_INFO: + currentFilter.info = currentFilter.settings = cell.isChecked(); + break; + case FILTER_INVITES: + currentFilter.invites = cell.isChecked(); + break; + case FILTER_CALLS: + currentFilter.group_call = cell.isChecked(); + break; + case FILTER_SECTION_MESSAGES: + if (clickedGroupExpand) { + sectionMessagesExpanded = !sectionMessagesExpanded; + } else { + currentFilter.delete = currentFilter.edit = currentFilter.pinned = cell.isChecked(); + } + break; + case FILTER_DELETE: + currentFilter.delete = cell.isChecked(); + break; + case FILTER_EDIT: + currentFilter.edit = cell.isChecked(); + break; + case FILTER_PIN: + currentFilter.pinned = cell.isChecked(); + break; + case BUTTON_ALL_ADMINS: + if (selectedAdmins == null) { + selectedAdmins = new LongSparseArray<>(); + } + selectedAdmins.clear(); + if (cell.isChecked() && currentAdmins != null) { + for (TLRPC.ChannelParticipant admin : currentAdmins) { + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + selectedAdmins.put(did, user); + } + } + break; + } + adapter.update(true); + } + if (item.id < 0) { + CheckBoxCell cell = (CheckBoxCell) view; + int index = (-item.id) - 1; + if (index < 0 || index >= currentAdmins.size()) return; + TLRPC.ChannelParticipant admin = currentAdmins.get(index); + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + if (selectedAdmins == null) { + selectedAdmins = new LongSparseArray<>(); + } + if (selectedAdmins.containsKey(did)) { + selectedAdmins.remove(did); + cell.setChecked(false, true); + } else { + selectedAdmins.put(did, user); + cell.setChecked(true, true); + } + adapter.update(true); + } + } + + public void setCurrentAdmins(ArrayList admins) { + currentAdmins = admins; + if (currentAdmins != null && selectedAdmins == null) { + selectedAdmins = new LongSparseArray<>(); + for (TLRPC.ChannelParticipant admin : currentAdmins) { + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + selectedAdmins.put(did, user); + } + } + if (adapter != null) { + adapter.update(true); + } + } + + private AdminLogFilterAlertDelegate delegate; + + public interface AdminLogFilterAlertDelegate { + void didSelectRights( + TLRPC.TL_channelAdminLogEventsFilter filter, + LongSparseArray admins + ); + } + + public void setAdminLogFilterAlertDelegate(AdminLogFilterAlertDelegate adminLogFilterAlertDelegate) { + delegate = adminLogFilterAlertDelegate; + } + + @Override + protected void onSmoothContainerViewLayout(float ty) { + super.onSmoothContainerViewLayout(ty); + buttonContainer.setTranslationY(-ty); + } + + @Override + protected boolean canDismissWithSwipe() { + return !recyclerListView.canScrollVertically(-1); + } +} 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 df1779e65..c9f2dd4d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -9,7 +9,6 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; -import static org.telegram.messenger.LocaleController.formatDateOnline; import static org.telegram.messenger.LocaleController.getString; import android.Manifest; @@ -47,11 +46,9 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.URLSpan; import android.util.Base64; -import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; -import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -136,8 +133,13 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; public class AlertsCreator { public final static int PERMISSIONS_REQUEST_TOP_ICON_SIZE = 72; @@ -973,7 +975,7 @@ public class AlertsCreator { return; } boolean enabled; - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did, false, false); String[] descriptions = new String[]{ LocaleController.getString("NotificationsTurnOn", R.string.NotificationsTurnOn), @@ -3733,6 +3735,7 @@ public class AlertsCreator { if (addPrivacyText != null) { FrameLayout frameLayout = new FrameLayout(context); LinkSpanDrawable.LinksTextView textView = new LinkSpanDrawable.LinksTextView(context); + textView.setPadding(dp(8), 0, dp(8), 0); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2, resourcesProvider)); textView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); @@ -3763,7 +3766,7 @@ public class AlertsCreator { bottomSheetParams.transitionFromLeft = true; bottomSheetParams.allowNestedScroll = false; fragment.showAsSheet(new PrivacyControlActivity(PrivacyControlActivity.PRIVACY_RULES_TYPE_BIRTHDAY), bottomSheetParams); - }), true)); + }), true, dp(8f / 3f), dp(.66f))); }; setText.run(); @@ -5182,6 +5185,8 @@ public class AlertsCreator { currentColor = preferences.getInt("GroupLed", 0xff0000ff); } else if (globalType == NotificationsController.TYPE_STORIES) { currentColor = preferences.getInt("StoriesLed", 0xff0000ff); + } else if (globalType == NotificationsController.TYPE_REACTIONS_STORIES || globalType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + currentColor = preferences.getInt("ReactionsLed", 0xff0000ff); } else { currentColor = preferences.getInt("ChannelLed", 0xff0000ff); } @@ -5229,6 +5234,8 @@ public class AlertsCreator { editor.putInt("GroupLed", selectedColor[0]); } else if (globalType == NotificationsController.TYPE_STORIES) { editor.putInt("StoriesLed", selectedColor[0]); + } else if (globalType == NotificationsController.TYPE_REACTIONS_STORIES || globalType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + editor.putInt("ReactionLed", selectedColor[0]); } else { editor.putInt("ChannelLed", selectedColor[0]); } @@ -5250,6 +5257,8 @@ public class AlertsCreator { editor.putInt("GroupLed", 0); } else if (globalType == NotificationsController.TYPE_STORIES) { editor.putInt("StoriesLed", 0); + } else if (globalType == NotificationsController.TYPE_REACTIONS_STORIES || globalType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + editor.putInt("ReactionsLed", 0); } else { editor.putInt("ChannelLed", 0); } @@ -5368,6 +5377,8 @@ public class AlertsCreator { NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_CHANNEL); } else if (prefKeyPrefix.equals("vibrate_group")) { NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_GROUP); + } else if (prefKeyPrefix.equals("vibrate_react")) { + NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_REACTIONS_MESSAGES); } else { NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_PRIVATE); } @@ -5385,32 +5396,37 @@ public class AlertsCreator { return builder.create(); } - public static Dialog createLocationUpdateDialog(final Activity parentActivity, TLRPC.User user, final MessagesStorage.IntCallback callback, Theme.ResourcesProvider resourcesProvider) { + public static Dialog createLocationUpdateDialog(final Activity parentActivity, boolean expand, TLRPC.User user, final MessagesStorage.IntCallback callback, Theme.ResourcesProvider resourcesProvider) { final int[] selected = new int[1]; String[] descriptions = new String[]{ - LocaleController.getString("SendLiveLocationFor15m", R.string.SendLiveLocationFor15m), - LocaleController.getString("SendLiveLocationFor1h", R.string.SendLiveLocationFor1h), - LocaleController.getString("SendLiveLocationFor8h", R.string.SendLiveLocationFor8h), + getString(R.string.SendLiveLocationFor15m), + getString(R.string.SendLiveLocationFor1h), + getString(R.string.SendLiveLocationFor8h), + getString(R.string.SendLiveLocationForever) }; final LinearLayout linearLayout = new LinearLayout(parentActivity); linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(0, 0, 0, dp(4)); TextView titleTextView = new TextView(parentActivity); - if (user != null) { - titleTextView.setText(LocaleController.formatString("LiveLocationAlertPrivate", R.string.LiveLocationAlertPrivate, UserObject.getFirstName(user))); + if (expand) { + titleTextView.setText(LocaleController.getString(R.string.LiveLocationAlertExpandMessage)); + } else if (user != null) { + titleTextView.setText(LocaleController.formatString(R.string.LiveLocationAlertPrivate, UserObject.getFirstName(user))); } else { - titleTextView.setText(LocaleController.getString("LiveLocationAlertGroup", R.string.LiveLocationAlertGroup)); + titleTextView.setText(LocaleController.getString(R.string.LiveLocationAlertGroup)); } int textColor = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_dialogTextBlack) : Theme.getColor(Theme.key_dialogTextBlack); titleTextView.setTextColor(textColor); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); titleTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - linearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 0, 24, 8)); + linearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, (expand ? 4 : 0), 24, 8)); for (int a = 0; a < descriptions.length; a++) { RadioColorCell cell = new RadioColorCell(parentActivity, resourcesProvider); + cell.heightDp = 42; cell.setPadding(dp(4), 0, dp(4), 0); cell.setTag(a); int color1 = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_radioBackground) : Theme.getColor(Theme.key_radioBackground); @@ -5431,8 +5447,12 @@ public class AlertsCreator { }); } AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity, resourcesProvider); - int topImageColor = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_dialogTopBackground) : Theme.getColor(Theme.key_dialogTopBackground); - builder.setTopImage(new ShareLocationDrawable(parentActivity, 0), topImageColor); + if (expand) { + builder.setTitle(getString(R.string.LiveLocationAlertExpandTitle)); + } else { + int topImageColor = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_dialogTopBackground) : Theme.getColor(Theme.key_dialogTopBackground); + builder.setTopImage(new ShareLocationDrawable(parentActivity, 0), topImageColor); + } builder.setView(linearLayout); builder.setPositiveButton(LocaleController.getString("ShareFile", R.string.ShareFile), (dialog, which) -> { int time; @@ -5440,8 +5460,10 @@ public class AlertsCreator { time = 15 * 60; } else if (selected[0] == 1) { time = 60 * 60; - } else { + } else if (selected[0] == 2) { time = 8 * 60 * 60; + } else { + time = 0x7FFFFFFF; } callback.run(time); }); @@ -5672,6 +5694,8 @@ public class AlertsCreator { selected[0] = preferences.getInt("priority_channel", 1); } else if (globalType == NotificationsController.TYPE_STORIES) { selected[0] = preferences.getInt("priority_stories", 1); + } else if (globalType == NotificationsController.TYPE_REACTIONS_MESSAGES || globalType == NotificationsController.TYPE_REACTIONS_STORIES) { + selected[0] = preferences.getInt("priority_react", 1); } if (selected[0] == 4) { selected[0] = 0; @@ -5744,6 +5768,9 @@ public class AlertsCreator { } else if (globalType == NotificationsController.TYPE_STORIES) { editor.putInt("priority_stories", option); selected[0] = preferences.getInt("priority_stories", 1); + } else if (globalType == NotificationsController.TYPE_REACTIONS_MESSAGES || globalType == NotificationsController.TYPE_REACTIONS_STORIES) { + editor.putInt("priority_react", option); + selected[0] = preferences.getInt("priority_react", 1); } NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(globalType); } @@ -5945,7 +5972,7 @@ public class AlertsCreator { void didPressedNewCard(); } - public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User user, TLRPC.Chat chat, TLRPC.EncryptedChat encryptedChat, TLRPC.ChatFull chatInfo, long mergeDialogId, MessageObject selectedMessage, SparseArray[] selectedMessages, MessageObject.GroupedMessages selectedGroup, int topicId, int mode, int loadParticipant, Runnable onDelete, Runnable hideDim, Theme.ResourcesProvider resourcesProvider) { + public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User user, TLRPC.Chat chat, TLRPC.EncryptedChat encryptedChat, TLRPC.ChatFull chatInfo, long mergeDialogId, MessageObject selectedMessage, SparseArray[] selectedMessages, MessageObject.GroupedMessages selectedGroup, int topicId, int mode, TLRPC.ChannelParticipant[] channelParticipants, Runnable onDelete, Runnable hideDim, Theme.ResourcesProvider resourcesProvider) { final boolean scheduled = mode == ChatActivity.MODE_SCHEDULED; final boolean isSavedMessages = mode == ChatActivity.MODE_SAVED; final boolean quickReplies = mode == ChatActivity.MODE_QUICK_REPLIES; @@ -5994,10 +6021,7 @@ public class AlertsCreator { } } - final boolean[] checks = new boolean[3]; final boolean[] deleteForAll = new boolean[1]; - TLRPC.User actionUser = null; - TLRPC.Chat actionChat = null; boolean canRevokeInbox = user != null && MessagesController.getInstance(currentAccount).canRevokePmInbox; int revokeTimeLimit; if (user != null) { @@ -6010,18 +6034,16 @@ public class AlertsCreator { int myMessagesCount = 0; boolean canDeleteInbox = encryptedChat == null && user != null && canRevokeInbox && revokeTimeLimit == 0x7fffffff; if (chat != null && chat.megagroup && !scheduled && !isSavedMessages) { - boolean canBan = ChatObject.canBlockUsers(chat); + ArrayList messages = new ArrayList<>(); if (selectedMessage != null) { if (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser) { - if (selectedMessage.messageOwner.from_id.user_id != 0) { - actionUser = MessagesController.getInstance(currentAccount).getUser(selectedMessage.messageOwner.from_id.user_id); - } else if (selectedMessage.messageOwner.from_id.channel_id != 0) { - actionChat = MessagesController.getInstance(currentAccount).getChat(selectedMessage.messageOwner.from_id.channel_id); - } else if (selectedMessage.messageOwner.from_id.chat_id != 0) { - actionChat = MessagesController.getInstance(currentAccount).getChat(selectedMessage.messageOwner.from_id.chat_id); + if (selectedGroup != null) { + messages.addAll(selectedGroup.messages); + } else { + messages.add(selectedMessage); } } boolean hasOutgoing = !selectedMessage.isSendError() && selectedMessage.getDialogId() == mergeDialogId && (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && selectedMessage.isOut() && (currentDate - selectedMessage.messageOwner.date) <= revokeTimeLimit; @@ -6029,23 +6051,6 @@ public class AlertsCreator { myMessagesCount++; } } else { - long from_id = -1; - for (int a = 1; a >= 0; a--) { - long channelId = 0; - for (int b = 0; b < selectedMessages[a].size(); b++) { - MessageObject msg = selectedMessages[a].valueAt(b); - if (from_id == -1) { - from_id = msg.getFromChatId(); - } - if (from_id < 0 || from_id != msg.getSenderId()) { - from_id = -2; - break; - } - } - if (from_id == -2) { - break; - } - } for (int a = 1; a >= 0; a--) { for (int b = 0; b < selectedMessages[a].size(); b++) { MessageObject msg = selectedMessages[a].valueAt(b); @@ -6056,77 +6061,97 @@ public class AlertsCreator { } } } + messages.add(msg); } } - if (from_id != -1) { - actionUser = MessagesController.getInstance(currentAccount).getUser(from_id); - } } - if ((actionUser != null && actionUser.id != UserConfig.getInstance(currentAccount).getClientUserId()) || (actionChat != null && !ChatObject.hasAdminRights(actionChat))) { - if (loadParticipant == 1 && !chat.creator && actionUser != null) { + + long clientUserId = UserConfig.getInstance(currentAccount).getClientUserId(); + ArrayList actionParticipants = messages + .stream() + .mapToLong(MessageObject::getFromChatId) + .distinct() + .mapToObj(fromId -> { + if (fromId > 0) { + return MessagesController.getInstance(currentAccount).getUser(fromId); + } else { + return MessagesController.getInstance(currentAccount).getChat(-fromId); + } + }) + .filter(Objects::nonNull) + .filter(userOrChat -> { + if (userOrChat instanceof TLRPC.User) { + TLRPC.User user1 = (TLRPC.User) userOrChat; + return user1.id != clientUserId; + } else if (userOrChat instanceof TLRPC.Chat) { + TLRPC.Chat chat1 = (TLRPC.Chat) userOrChat; + return !ChatObject.hasAdminRights(chat1); + } + return false; + }) + .collect(Collectors.toCollection(ArrayList::new)); + + if (!actionParticipants.isEmpty()) { + if (channelParticipants == null) { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(activity, AlertDialog.ALERT_TYPE_SPINNER)}; - TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); - req.channel = MessagesController.getInputChannel(chat); - req.participant = MessagesController.getInputPeer(actionUser); - int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - try { - progressDialog[0].dismiss(); - } catch (Throwable ignore) { + final int participantCount = actionParticipants.size(); + TLRPC.ChannelParticipant[] channelParticipantsLoad = new TLRPC.ChannelParticipant[participantCount]; + int[] requestIds = new int[participantCount]; + int[] responseCounter = new int[1]; - } - progressDialog[0] = null; - int loadType = 2; - if (response != null) { - TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; - if (!(participant.participant instanceof TLRPC.TL_channelParticipantAdmin || participant.participant instanceof TLRPC.TL_channelParticipantCreator)) { - loadType = 0; + for (int i = 0; i < participantCount; i++) { + TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); + req.channel = MessagesController.getInputChannel(chat); + req.participant = MessagesController.getInputPeer(actionParticipants.get(i)); + final int index = i; + requestIds[i] = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + responseCounter[0]++; + requestIds[index] = 0; + + if (response != null) { + TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; + channelParticipantsLoad[index] = participant.participant; } - } else if (error != null && "USER_NOT_PARTICIPANT".equals(error.text)) { - loadType = 0; - } - createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, topicId, mode, loadType, onDelete, hideDim, resourcesProvider); - })); + + if (responseCounter[0] == participantCount) { + try { + progressDialog[0].dismiss(); + } catch (Throwable ignore) { + } + progressDialog[0] = null; + + createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, topicId, mode, channelParticipantsLoad, onDelete, hideDim, resourcesProvider); + } + })); + } + AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } - progressDialog[0].setOnCancelListener(dialog -> ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true)); + progressDialog[0].setOnCancelListener(dialog -> { + for (int requestId : requestIds) { + if (requestId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true); + } + } + if (hideDim != null) { + hideDim.run(); + } + }); fragment.showDialog(progressDialog[0]); }, 1000); return; } - FrameLayout frameLayout = new FrameLayout(activity); - int num = 0; - String name = actionUser != null ? ContactsController.formatName(actionUser.first_name, actionUser.last_name) : actionChat.title; - for (int a = 0; a < 3; a++) { - if ((loadParticipant == 2 || !canBan) && a == 0) { - continue; - } - CheckBoxCell cell = new CheckBoxCell(activity, 1, resourcesProvider); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - cell.setTag(a); - if (a == 0) { - 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 { - cell.setText(LocaleController.formatString("DeleteAllFrom", R.string.DeleteAllFrom, name), "", false, false); - } - cell.setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 48 * num, 0, 0)); - cell.setOnClickListener(v -> { - if (!v.isEnabled()) { - return; - } - CheckBoxCell cell13 = (CheckBoxCell) v; - Integer num1 = (Integer) cell13.getTag(); - checks[num1] = !checks[num1]; - cell13.setChecked(checks[num1], true); + DeleteMessagesBottomSheet deleteMessagesBottomSheet = new DeleteMessagesBottomSheet(fragment, chat, messages, actionParticipants, channelParticipants, mergeDialogId, topicId, mode, onDelete); + if (hideDim != null) { + deleteMessagesBottomSheet.setOnHideListener(i -> { + hideDim.run(); }); - num++; } - builder.setView(frameLayout); + deleteMessagesBottomSheet.show(); + return; } else if (!hasNotOut && myMessagesCount > 0 && hasNonDiceMessages) { hasDeleteForAllCheck = true; FrameLayout frameLayout = new FrameLayout(activity); @@ -6146,8 +6171,6 @@ public class AlertsCreator { }); builder.setView(frameLayout); builder.setCustomViewOffset(9); - } else { - actionUser = null; } } else if (!scheduled && !isSavedMessages && !ChatObject.isChannel(chat) && encryptedChat == null) { if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && (!user.bot || user.support) || chat != null) { @@ -6209,8 +6232,6 @@ public class AlertsCreator { builder.setCustomViewOffset(9); } } - final TLRPC.User userFinal = actionUser; - final TLRPC.Chat chatFinal = actionChat; DialogInterface.OnClickListener deleteAction = (dialogInterface, i) -> { ArrayList ids = null; @@ -6239,6 +6260,9 @@ public class AlertsCreator { random_ids.add(selectedMessage.messageOwner.random_id); } } + if (mergeDialogId != 0 && selectedMessage.messageOwner.peer_id != null && selectedMessage.messageOwner.peer_id.chat_id == -mergeDialogId) { + thisDialogId = mergeDialogId; + } MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, thisDialogId, topicId, deleteForAll[0], mode); } else { for (int a = 1; a >= 0; a--) { @@ -6256,31 +6280,10 @@ public class AlertsCreator { } } } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, thisDialogId, topicId, deleteForAll[0], mode); + MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, (a == 1 && mergeDialogId != 0) ? mergeDialogId : thisDialogId, topicId, deleteForAll[0], mode); selectedMessages[a].clear(); } } - if (userFinal != null || chatFinal != null) { - if (checks[0]) { - MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat.id, userFinal, chatFinal, false, false); - } - if (checks[1]) { - TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); - req.channel = MessagesController.getInputChannel(chat); - if (userFinal != null) { - req.participant = MessagesController.getInputPeer(userFinal); - } else { - req.participant = MessagesController.getInputPeer(chatFinal); - } - req.id = ids; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - - }); - } - if (checks[2]) { - MessagesController.getInstance(currentAccount).deleteUserChannelHistory(chat, userFinal, chatFinal, 0); - } - } if (onDelete != null) { onDelete.run(); } @@ -6839,11 +6842,7 @@ public class AlertsCreator { public static ActionBarPopupWindow showPopupMenu(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, View anchorView, int offsetX, int offsetY) { Rect rect = new Rect(); ActionBarPopupWindow popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); - if (Build.VERSION.SDK_INT >= 19) { - popupWindow.setAnimationStyle(0); - } else { - popupWindow.setAnimationStyle(R.style.PopupAnimation); - } + popupWindow.setAnimationStyle(R.style.PopupAnimation); popupWindow.setAnimationEnabled(true); @@ -6866,7 +6865,8 @@ public class AlertsCreator { popupWindow.showAsDropDown(anchorView, offsetX, offsetY); popupLayout.updateRadialSelectors(); - popupWindow.startAnimation(); +// popupWindow.startAnimation(); + ActionBarPopupWindow.startAnimation(popupLayout); popupLayout.setOnTouchListener((v, event) -> { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java index 8aff260ad..0f0f08187 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -573,7 +573,8 @@ public class AnimatedEmojiDrawable extends Drawable { if ("video/webm".equals(document.mime_type)) { mediaLocation = ImageLocation.getForDocument(document); mediaFilter = filter + "_" + ImageLoader.AUTOPLAY_FILTER; - thumbDrawable = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, true); + thumbDrawable = svgThumb; } else if ("application/x-tgsticker".equals(document.mime_type)) { String probableCacheKey = (cacheType != 0 ? cacheType + "_" : "") + documentId + "@" + filter; if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW || (cacheType == CACHE_TYPE_KEYBOARD || !ImageLoader.getInstance().hasLottieMemCache(probableCacheKey))) { @@ -586,7 +587,7 @@ public class AnimatedEmojiDrawable extends Drawable { mediaLocation = ImageLocation.getForDocument(document); mediaFilter = filter; } else { - SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, true); if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, true)) { svgThumb.overrideWidthAndHeight(512, 512); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java index b8f95cc97..a7c9dacbd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java @@ -28,6 +28,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LiteMode; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -1058,13 +1059,14 @@ public class AnimatedEmojiSpan extends ReplacementSpan { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - float offset = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : 0; - if (offset != 0) { + float offsetY = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : 0; + float offsetX = LocaleController.isRTL ? getPaddingRight() : getPaddingLeft(); + if (offsetY != 0 || offsetX != 0) { canvas.save(); - canvas.translate(0, offset); + canvas.translate(offsetX, offsetY); } AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), stack, 0, null, 0, 0, 0, 1f); - if (offset != 0) { + if (offsetY != 0 || offsetX != 0) { canvas.restore(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java index 15a350f4a..7c88af13c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java @@ -145,6 +145,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, private volatile boolean isRunning; private volatile boolean isRecycled; public volatile long nativePtr; + private boolean ptrFail; private DispatchQueue decodeQueue; private float startTime; private float endTime; @@ -356,18 +357,20 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } private int decoderTryCount = 0; + private final int MAX_TRIES = 15; private Runnable loadFrameRunnable = new Runnable() { @Override public void run() { if (!isRecycled) { if (!decoderCreated && nativePtr == 0) { nativePtr = createDecoder(path.getAbsolutePath(), metaData, currentAccount, streamFileSize, stream, false); + ptrFail = nativePtr == 0 && (!isWebmSticker || decoderTryCount > MAX_TRIES); if (nativePtr != 0 && (metaData[0] > 3840 || metaData[1] > 3840)) { destroyDecoder(nativePtr); nativePtr = 0; } updateScaleFactor(); - decoderCreated = !isWebmSticker || nativePtr != 0 || (decoderTryCount++) > 15; + decoderCreated = !isWebmSticker || nativePtr != 0 || (decoderTryCount++) > MAX_TRIES; } try { if (bitmapsCache != null) { @@ -502,6 +505,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } if (createDecoder && !this.precache) { nativePtr = createDecoder(file.getAbsolutePath(), metaData, currentAccount, streamFileSize, stream, preview); + ptrFail = nativePtr == 0 && (!isWebmSticker || decoderTryCount > MAX_TRIES); if (nativePtr != 0 && (metaData[0] > 3840 || metaData[1] > 3840)) { destroyDecoder(nativePtr); nativePtr = 0; @@ -511,6 +515,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } if (this.precache) { nativePtr = createDecoder(file.getAbsolutePath(), metaData, currentAccount, streamFileSize, stream, preview); + ptrFail = nativePtr == 0 && (!isWebmSticker || decoderTryCount > MAX_TRIES); if (nativePtr != 0 && (metaData[0] > 3840 || metaData[1] > 3840)) { destroyDecoder(nativePtr); nativePtr = 0; @@ -1088,7 +1093,11 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, } public boolean isRecycled() { - return isRecycled || decoderTryCount >= 15; + return isRecycled || decoderTryCount >= MAX_TRIES; + } + + public boolean decoderFailed() { + return decoderCreated && ptrFail; } public Bitmap getNextFrame(boolean loop) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java index ffb7c0c60..0fed232e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -118,9 +118,9 @@ public class AnimatedTextView extends View { private boolean toSetTextMoveDown; private long animateDelay = 0; - private long animateDuration = 450; + private long animateDuration = 320; private TimeInterpolator animateInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; - private float moveAmplitude = 1f; + private float moveAmplitude = .3f; private float scaleAmplitude = 0; @@ -152,6 +152,8 @@ public class AnimatedTextView extends View { private Matrix ellipsizeGradientMatrix; private Paint ellipsizePaint; + private boolean includeFontPadding = true; + public AnimatedTextDrawable() { this(false, false, false); } @@ -319,6 +321,10 @@ public class AnimatedTextView extends View { invalidateSelf(); } + public float getRightPadding() { + return this.rightPadding; + } + public void cancelAnimation() { if (animator != null) { animator.cancel(); @@ -551,6 +557,7 @@ public class AnimatedTextView extends View { .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setEllipsize(TextUtils.TruncateAt.END) .setEllipsizedWidth(width) + .setIncludePad(includeFontPadding) .build(); } else { return new StaticLayout( @@ -561,7 +568,7 @@ public class AnimatedTextView extends View { Layout.Alignment.ALIGN_NORMAL, 1, 0, - false, + includeFontPadding, TextUtils.TruncateAt.END, width ); @@ -1072,6 +1079,10 @@ public class AnimatedTextView extends View { public void setOnWidthUpdatedListener(Runnable listener) { widthUpdatedListener = listener; } + + public void setIncludeFontPadding(boolean includeFontPadding) { + this.includeFontPadding = includeFontPadding; + } } private final AnimatedTextDrawable drawable; @@ -1112,7 +1123,7 @@ public class AnimatedTextView extends View { } if (lastMaxWidth != width && getLayoutParams().width != 0) { drawable.setBounds(getPaddingLeft(), getPaddingTop(), width - getPaddingRight(), height - getPaddingBottom()); - setText(drawable.getText(), false); + drawable.setText(drawable.getText(), false, true); } lastMaxWidth = width; if (adaptWidth && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { @@ -1263,8 +1274,16 @@ public class AnimatedTextView extends View { drawable.setRightPadding(rightPadding); } + public float getRightPadding() { + return drawable.getRightPadding(); + } + private Runnable widthUpdatedListener; public void setOnWidthUpdatedListener(Runnable listener) { drawable.setOnWidthUpdatedListener(listener); } + + public void setIncludeFontPadding(boolean includeFontPadding) { + this.drawable.setIncludeFontPadding(includeFontPadding); + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java index 76dd519c9..01171bd15 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java @@ -28,6 +28,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.INavigationLayout; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.DialogsActivity; import org.telegram.ui.ProfileActivity; import org.telegram.ui.TopicsFragment; @@ -43,6 +44,7 @@ public class BackButtonMenu { int stackIndex; TLRPC.Chat chat; TLRPC.User user; + TLRPC.TL_forumTopic topic; long dialogId; int folderId; int filterId; @@ -60,7 +62,6 @@ public class BackButtonMenu { } ArrayList dialogs; if (topicId != 0) { - new ArrayList<>(); dialogs = getStackedHistoryForTopic(thisFragment, currentDialogId, topicId); } else { dialogs = getStackedHistoryDialogs(thisFragment, currentDialogId); @@ -82,6 +83,7 @@ public class BackButtonMenu { final PulledDialog pDialog = dialogs.get(i); final TLRPC.Chat chat = pDialog.chat; final TLRPC.User user = pDialog.user; + final TLRPC.TL_forumTopic topic = pDialog.topic; FrameLayout cell = new FrameLayout(context); cell.setMinimumWidth(AndroidUtilities.dp(200)); @@ -104,7 +106,19 @@ public class BackButtonMenu { avatarDrawable.setScaleSize(.8f); Drawable thumb = avatarDrawable; boolean addDivider = false; - if (chat != null) { + if (topic != null) { + if (topic.id == 1) { + thumb = ForumUtilities.createGeneralTopicDrawable(fragmentView.getContext(), 1f, Theme.getColor(Theme.key_chat_inMenu, resourcesProvider), false); + imageView.setImageDrawable(thumb); + } else if (topic.icon_emoji_id != 0) { + AnimatedEmojiDrawable animatedEmojiDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_FORUM_TOPIC, thisFragment.getCurrentAccount(), topic.icon_emoji_id); + imageView.setAnimatedEmojiDrawable(animatedEmojiDrawable); + } else { + thumb = ForumUtilities.createTopicDrawable(topic, false); + imageView.setImageDrawable(thumb); + } + titleView.setText(topic.title); + } else if (chat != null) { avatarDrawable.setInfo(thisFragment.getCurrentAccount(), chat); if (chat.photo != null && chat.photo.strippedBitmap != null) { thumb = chat.photo.strippedBitmap; @@ -150,17 +164,21 @@ public class BackButtonMenu { } if (pDialog.stackIndex >= 0) { Long nextFragmentDialogId = null; + Long nextFragmentTopicId = null; if (parentLayout == null || parentLayout.getFragmentStack() == null || pDialog.stackIndex >= parentLayout.getFragmentStack().size()) { nextFragmentDialogId = null; + nextFragmentTopicId = null; } else { BaseFragment nextFragment = parentLayout.getFragmentStack().get(pDialog.stackIndex); if (nextFragment instanceof ChatActivity) { nextFragmentDialogId = ((ChatActivity) nextFragment).getDialogId(); + nextFragmentTopicId = ((ChatActivity) nextFragment).getTopicId(); } else if (nextFragment instanceof ProfileActivity) { nextFragmentDialogId = ((ProfileActivity) nextFragment).getDialogId(); + nextFragmentTopicId = ((ProfileActivity) nextFragment).getTopicId(); } } - if (nextFragmentDialogId != null && nextFragmentDialogId != pDialog.dialogId) { + if (nextFragmentDialogId != null && nextFragmentDialogId != pDialog.dialogId || topic != null && nextFragmentTopicId != null && topic.id != nextFragmentTopicId) { for (int j = parentLayout.getFragmentStack().size() - 2; j > pDialog.stackIndex; --j) { parentLayout.removeFragmentFromStack(j); } @@ -221,7 +239,14 @@ public class BackButtonMenu { private static ArrayList getStackedHistoryForTopic(BaseFragment thisFragment, long currentDialogId, long topicId) { ArrayList dialogs = new ArrayList<>(); - if (thisFragment.getParentLayout().getFragmentStack().size() > 1 && thisFragment.getParentLayout().getFragmentStack().get(thisFragment.getParentLayout().getFragmentStack().size() - 2) instanceof TopicsFragment) { + if (thisFragment == null) { + return dialogs; + } + final INavigationLayout parentLayout = thisFragment.getParentLayout(); + if (parentLayout == null) { + return dialogs; + } + if (parentLayout.getFragmentStack().size() > 1 && parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2) instanceof TopicsFragment) { PulledDialog pulledDialog = new PulledDialog(); dialogs.add(pulledDialog); pulledDialog.stackIndex = 0; @@ -229,18 +254,28 @@ public class BackButtonMenu { pulledDialog = new PulledDialog(); dialogs.add(pulledDialog); - pulledDialog.stackIndex = thisFragment.getParentLayout().getFragmentStack().size() - 2; + pulledDialog.stackIndex = parentLayout.getFragmentStack().size() - 2; pulledDialog.activity = TopicsFragment.class; pulledDialog.chat = MessagesController.getInstance(thisFragment.getCurrentAccount()).getChat(-currentDialogId); - return dialogs; } else { PulledDialog pulledDialog = new PulledDialog(); dialogs.add(pulledDialog); pulledDialog.stackIndex = -1; pulledDialog.activity = TopicsFragment.class; pulledDialog.chat = MessagesController.getInstance(thisFragment.getCurrentAccount()).getChat(-currentDialogId); - return dialogs; } + List pulledDialogs = parentLayout.getPulledDialogs(); + if (pulledDialogs != null) { + for (int i = 0; i < pulledDialogs.size(); i++) { + PulledDialog pulledDialog = pulledDialogs.get(i); + if (pulledDialog.topic == null || pulledDialog.topic.id == topicId) { + continue; + } + dialogs.add(pulledDialog); + } + } + Collections.sort(dialogs, (d1, d2) -> d2.stackIndex - d1.stackIndex); + return dialogs; } public static void goToPulledDialog(BaseFragment fragment, PulledDialog dialog) { @@ -256,7 +291,12 @@ public class BackButtonMenu { } bundle.putInt("dialog_folder_id", dialog.folderId); bundle.putInt("dialog_filter_id", dialog.filterId); - fragment.presentFragment(new ChatActivity(bundle), true); + if (dialog.topic != null) { + ChatActivity chatActivity = ForumUtilities.getChatActivityForTopic(fragment, dialog.chat.id, dialog.topic, 0, bundle); + fragment.presentFragment(chatActivity, true); + } else { + fragment.presentFragment(new ChatActivity(bundle), true); + } } else if (dialog.activity == ProfileActivity.class) { Bundle bundle = new Bundle(); bundle.putLong("dialog_id", dialog.dialogId); @@ -360,7 +400,7 @@ public class BackButtonMenu { return dialogs; } - public static void addToPulledDialogs(BaseFragment thisFragment, int stackIndex, TLRPC.Chat chat, TLRPC.User user, long dialogId, int folderId, int filterId) { + public static void addToPulledDialogs(BaseFragment thisFragment, int stackIndex, TLRPC.Chat chat, TLRPC.User user, TLRPC.TL_forumTopic topic, long dialogId, int folderId, int filterId) { if (chat == null && user == null) { return; } @@ -376,7 +416,7 @@ public class BackButtonMenu { } boolean alreadyAdded = false; for (PulledDialog d : parentLayout.getPulledDialogs()) { - if (d.dialogId == dialogId) { + if (topic == null && d.dialogId == dialogId || topic != null && d.topic.id == topic.id) { alreadyAdded = true; break; } @@ -391,6 +431,7 @@ public class BackButtonMenu { d.folderId = folderId; d.chat = chat; d.user = user; + d.topic = topic; parentLayout.getPulledDialogs().add(d); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java index cf4d4f584..302599f45 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java @@ -11,6 +11,7 @@ public class BlurredRecyclerView extends RecyclerListView { public int blurTopPadding; public int topPadding; + public int bottomPadding; boolean globalIgnoreLayout; public int additionalClipBottom; @@ -75,6 +76,7 @@ public class BlurredRecyclerView extends RecyclerListView { @Override public void setPadding(int left, int top, int right, int bottom) { topPadding = top; - super.setPadding(left, topPadding + blurTopPadding, right, bottom); + bottomPadding = bottom; + super.setPadding(left, topPadding + blurTopPadding, right, bottomPadding); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java index 67efd2813..d5d0f8cd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -1,7 +1,11 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.view.MotionEvent; import android.view.View; @@ -9,6 +13,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.LinearLayoutManager; @@ -20,17 +25,25 @@ import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; public abstract class BottomSheetWithRecyclerListView extends BottomSheet { + public enum ActionBarType { + FADING, + SLIDING + } + private final Drawable headerShadowDrawable; + protected LinearLayoutManager layoutManager; protected RecyclerListView recyclerListView; protected ActionBar actionBar; boolean wasDrawn; protected int contentHeight; private BaseFragment baseFragment; public final boolean hasFixedSize; + public final boolean stackFromEnd; protected boolean clipToActionBar; public NestedSizeNotifierLayout nestedSizeNotifierLayout; @@ -38,6 +51,23 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { boolean showShadow = true; private float shadowAlpha = 1f; + private boolean showHandle = false; + private RectF handleRect = new RectF(); + + private ActionBarType actionBarType = ActionBarType.FADING; + protected int headerTotalHeight = 0; + protected int headerHeight = 0; + protected int headerPaddingTop = 0; + protected int headerPaddingBottom = 0; + protected boolean actionBarIgnoreTouchEvents = false; + protected AnimatedFloat actionBarSlideProgress; + + /* + Take padding-view translationY into account when positioning background. + If set to true requires that changes to its translation invalidate containerView. + */ + protected boolean takeTranslationIntoAccount = false; + public BottomSheetWithRecyclerListView(BaseFragment fragment, boolean needFocus, boolean hasFixedSize) { this(fragment, needFocus, hasFixedSize, false, fragment == null ? null : fragment.getResourceProvider()); } @@ -46,10 +76,25 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { this(fragment.getParentActivity(), fragment, needFocus, hasFixedSize, useNested, resourcesProvider); } + public BottomSheetWithRecyclerListView(BaseFragment fragment, boolean needFocus, boolean hasFixedSize, ActionBarType actionBarType) { + this(fragment.getParentActivity(), fragment, needFocus, hasFixedSize, false, actionBarType, fragment.getResourceProvider()); + } + public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, boolean needFocus, boolean hasFixedSize, boolean useNested, Theme.ResourcesProvider resourcesProvider) { + this(context, fragment, needFocus, hasFixedSize, useNested, ActionBarType.FADING, resourcesProvider); + } + + @SuppressLint("AppCompatCustomView") + public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, boolean needFocus, boolean hasFixedSize, boolean useNested, ActionBarType actionBarType, Theme.ResourcesProvider resourcesProvider) { + this(context, fragment, needFocus, hasFixedSize, useNested, false, actionBarType, resourcesProvider); + } + + @SuppressLint("AppCompatCustomView") + public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, boolean needFocus, boolean hasFixedSize, boolean useNested, boolean stackFromEnd, ActionBarType actionBarType, Theme.ResourcesProvider resourcesProvider) { super(context, needFocus, resourcesProvider); this.baseFragment = fragment; this.hasFixedSize = hasFixedSize; + this.stackFromEnd = stackFromEnd; headerShadowDrawable = ContextCompat.getDrawable(context, R.drawable.header_shadow).mutate(); FrameLayout containerView; if (useNested) { @@ -59,6 +104,9 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { contentHeight = MeasureSpec.getSize(heightMeasureSpec); onPreMeasure(widthMeasureSpec, heightMeasureSpec); + if (stackFromEnd) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY); + } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -96,6 +144,9 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { contentHeight = MeasureSpec.getSize(heightMeasureSpec); onPreMeasure(widthMeasureSpec, heightMeasureSpec); + if (stackFromEnd) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY); + } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -127,8 +178,18 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { } }; } - recyclerListView = new RecyclerListView(context, resourcesProvider); - recyclerListView.setLayoutManager(new LinearLayoutManager(context)); + recyclerListView = new RecyclerListView(context, resourcesProvider) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + applyScrolledPosition(); + super.onLayout(changed, l, t, r, b); + } + }; + layoutManager = new LinearLayoutManager(context); + if (stackFromEnd) { + layoutManager.setStackFromEnd(true); + } + recyclerListView.setLayoutManager(layoutManager); if (nestedSizeNotifierLayout != null) { nestedSizeNotifierLayout.setBottomSheetContainerView(getContainer()); nestedSizeNotifierLayout.setTargetListView(recyclerListView); @@ -156,6 +217,14 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { super.setTag(tag); updateStatusBar(); } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (actionBarIgnoreTouchEvents) { + return false; + } + return super.dispatchTouchEvent(ev); + } }; actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -185,13 +254,30 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { } }); } + if (actionBarType == ActionBarType.SLIDING) { + setSlidingActionBar(); + } onViewCreated(containerView); updateStatusBar(); } + public void setSlidingActionBar() { + if (hasFixedSize) { + return; + } + actionBarType = ActionBarType.SLIDING; + headerHeight = ActionBar.getCurrentActionBarHeight(); + headerTotalHeight = headerHeight + AndroidUtilities.statusBarHeight; + headerPaddingTop = dp(16); + headerPaddingBottom = dp(-20); + actionBarSlideProgress = new AnimatedFloat(containerView, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + actionBar.backButtonImageView.setPivotX(0.0f); + recyclerListView.setClipToPadding(true); + } + protected void resetAdapter(Context context) { RecyclerListView.SelectionAdapter adapter = createAdapter(recyclerListView); - recyclerListView.setAdapter(new RecyclerListView.SelectionAdapter() { + RecyclerListView.SelectionAdapter wrapperAdapter = new RecyclerListView.SelectionAdapter() { @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { @@ -207,12 +293,22 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int h; if (contentHeight == 0) { - h = AndroidUtilities.dp(300); + h = dp(300); } else { h = (int) (contentHeight * topPadding); } + h -= headerTotalHeight - headerHeight - headerPaddingTop - headerPaddingBottom; + if (h < 1) { + h = 1; + } super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + containerView.invalidate(); + } }; return new RecyclerListView.Holder(view); } @@ -238,27 +334,71 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { public int getItemCount() { return 1 + adapter.getItemCount(); } - }); + + @Override + public void registerAdapterDataObserver(@NonNull RecyclerView.AdapterDataObserver observer) { + adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + observer.onChanged(); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + observer.onItemRangeChanged(positionStart + 1, itemCount); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) { + observer.onItemRangeChanged(positionStart + 1, itemCount, payload); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + observer.onItemRangeInserted(positionStart + 1, itemCount); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + observer.onItemRangeRemoved(positionStart + 1, itemCount); + } + + @Override + public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { + observer.onItemRangeMoved(fromPosition + 1, toPosition + 1, itemCount); + } + }); + } + }; + recyclerListView.setAdapter(wrapperAdapter); } private void postDrawInternal(Canvas canvas, View parentView) { - if (showShadow && shadowAlpha != 1f) { - shadowAlpha += 16 / 150f; - parentView.invalidate(); - } else if (!showShadow && shadowAlpha != 0) { - shadowAlpha -= 16 / 150f; - parentView.invalidate(); - } - shadowAlpha = Utilities.clamp(shadowAlpha, 1f, 0f); - if (actionBar != null && actionBar.getVisibility() == View.VISIBLE && actionBar.getAlpha() != 0 && shadowAlpha != 0) { - headerShadowDrawable.setBounds(backgroundPaddingLeft, actionBar.getBottom(), parentView.getMeasuredWidth() - backgroundPaddingLeft, actionBar.getBottom() + headerShadowDrawable.getIntrinsicHeight()); - headerShadowDrawable.setAlpha((int) (255 * actionBar.getAlpha() * shadowAlpha)); - headerShadowDrawable.draw(canvas); - if (headerShadowDrawable.getAlpha() < 255) { + if (actionBarType == ActionBarType.FADING) { + if (showShadow && shadowAlpha != 1f) { + shadowAlpha += 16 / 150f; + parentView.invalidate(); + } else if (!showShadow && shadowAlpha != 0) { + shadowAlpha -= 16 / 150f; parentView.invalidate(); } + shadowAlpha = Utilities.clamp(shadowAlpha, 1f, 0f); + if (actionBar != null && actionBar.getVisibility() == View.VISIBLE && actionBar.getAlpha() != 0 && shadowAlpha != 0) { + headerShadowDrawable.setBounds(backgroundPaddingLeft, actionBar.getBottom(), parentView.getMeasuredWidth() - backgroundPaddingLeft, actionBar.getBottom() + headerShadowDrawable.getIntrinsicHeight()); + headerShadowDrawable.setAlpha((int) (255 * actionBar.getAlpha() * shadowAlpha)); + headerShadowDrawable.draw(canvas); + if (headerShadowDrawable.getAlpha() < 255) { + parentView.invalidate(); + } + } + wasDrawn = true; + } else if (actionBarType == ActionBarType.SLIDING) { + if ((int) (255 * shadowAlpha) != 0) { + headerShadowDrawable.setBounds(backgroundPaddingLeft, actionBar.getBottom() + (int) actionBar.getTranslationY(), parentView.getMeasuredWidth() - backgroundPaddingLeft, actionBar.getBottom() + (int) actionBar.getTranslationY() + headerShadowDrawable.getIntrinsicHeight()); + headerShadowDrawable.setAlpha((int) (255 * shadowAlpha)); + headerShadowDrawable.draw(canvas); + } } - wasDrawn = true; } private void preDrawInternal(Canvas canvas, View parent) { @@ -267,14 +407,49 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { int top = -AndroidUtilities.dp(16); if (holder != null) { top = holder.itemView.getBottom() - AndroidUtilities.dp(16); + if (takeTranslationIntoAccount) { + top += (int) holder.itemView.getTranslationY(); + } + } + top = top - headerHeight - headerPaddingTop - headerPaddingBottom; + + float handleAlpha = 1.0f; + float progressToFullView = 0.0f; + if (actionBarType == ActionBarType.FADING) { + progressToFullView = 1f - (top + AndroidUtilities.dp(16)) / (float) AndroidUtilities.dp(56); + if (progressToFullView < 0) { + progressToFullView = 0; + } + AndroidUtilities.updateViewVisibilityAnimated(actionBar, progressToFullView != 0f, 1f, wasDrawn); + } else if (actionBarType == ActionBarType.SLIDING) { + float actionBarY = Math.max(top + dp(8) + headerPaddingTop - AndroidUtilities.statusBarHeight, 0.0f); + float t = actionBarSlideProgress.set(actionBarY == 0.0f ? 1.0f : 0.0f); + progressToFullView = t; + shadowAlpha = t; + handleAlpha = AndroidUtilities.lerp(1.0f, 0.5f, t); + actionBar.backButtonImageView.setAlpha(t); + actionBar.backButtonImageView.setScaleX(t); + actionBar.backButtonImageView.setPivotY(actionBar.backButtonImageView.getMeasuredHeight() / 2f); + actionBar.backButtonImageView.setScaleY(t); + SimpleTextView titleTextView = actionBar.getTitleTextView(); + titleTextView.setTranslationX(AndroidUtilities.lerp(dp(21) - titleTextView.getLeft(), 0.0f, t)); + actionBar.setTranslationY(actionBarY); + top -= AndroidUtilities.lerp(0, headerTotalHeight - headerHeight - headerPaddingTop - headerPaddingBottom + dp(13), t); + actionBar.getBackground().setBounds(0, AndroidUtilities.lerp(actionBar.getHeight(), 0, t), actionBar.getWidth(), actionBar.getHeight()); + + if (t > 0.5f) { + if (actionBarIgnoreTouchEvents) { + actionBarIgnoreTouchEvents = false; + actionBar.setTag(1); + } + } else { + if (!actionBarIgnoreTouchEvents) { + actionBarIgnoreTouchEvents = true; + actionBar.setTag(null); + } + } } - float progressToFullView = 1f - (top + AndroidUtilities.dp(16)) / (float) AndroidUtilities.dp(56); - if (progressToFullView < 0) { - progressToFullView = 0; - } - - AndroidUtilities.updateViewVisibilityAnimated(actionBar, progressToFullView != 0f, 1f, wasDrawn); if (needPaddingShadow()) { shadowDrawable.setBounds(0, top, parent.getMeasuredWidth(), parent.getMeasuredHeight()); } else { @@ -282,6 +457,16 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { } shadowDrawable.draw(canvas); + if (showHandle && handleAlpha > 0) { + int w = dp(36); + int y = top + AndroidUtilities.dp(20); + handleRect.set((parent.getMeasuredWidth() - w) / 2.0f, y, (parent.getMeasuredWidth() + w) / 2.0f, y + dp(4)); + int color = getThemedColor(Theme.key_sheet_scrollUp); + Theme.dialogs_onlineCirclePaint.setColor(color); + Theme.dialogs_onlineCirclePaint.setAlpha((int) (Theme.dialogs_onlineCirclePaint.getAlpha() * handleAlpha)); + canvas.drawRoundRect(handleRect, dp(2), dp(2), Theme.dialogs_onlineCirclePaint); + } + onPreDraw(canvas, top, progressToFullView); } } @@ -342,4 +527,49 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { nestedSizeNotifierLayout.invalidate(); } + public void setShowHandle(boolean showHandle) { + this.showHandle = showHandle; + } + + + private int savedScrollPosition = -1; + private int savedScrollOffset; + public void saveScrollPosition() { + if (recyclerListView != null && layoutManager != null && recyclerListView.getChildCount() > 0) { + View view = null; + int position = -1; + int top = Integer.MAX_VALUE; + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + View child = recyclerListView.getChildAt(i); + int childPosition = recyclerListView.getChildAdapterPosition(child); + if (childPosition > 0 && child.getTop() < top) { + view = child; + position = childPosition; + top = child.getTop(); + } + } + if (view != null) { + savedScrollPosition = position; + savedScrollOffset = view.getTop() + containerView.getTop(); + smoothContainerViewLayout(); + } + } + } + + public void applyScrolledPosition() { + this.applyScrolledPosition(false); + } + + public void applyScrolledPosition(boolean ignorePaddingView) { + if (recyclerListView != null && layoutManager != null && savedScrollPosition >= 0) { + int offset = savedScrollOffset - containerView.getTop() - recyclerListView.getPaddingTop(); + RecyclerView.ViewHolder paddingViewHolder = recyclerListView.findViewHolderForAdapterPosition(0); + if (ignorePaddingView && paddingViewHolder != null) { + View view = paddingViewHolder.itemView; + offset -= Math.max(view.getBottom() - recyclerListView.getPaddingTop(), 0); + } + layoutManager.scrollToPositionWithOffset(savedScrollPosition, offset); + savedScrollPosition = -1; + } + } } 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 a4b6c6b6a..718e415e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -23,14 +23,10 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.method.LinkMovementMethod; -import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.GestureDetector; @@ -627,6 +623,10 @@ public class Bulletin { return 0; } + default boolean bottomOffsetAnimated() { + return true; + } + default int getLeftPadding() { return 0; } @@ -875,7 +875,7 @@ public class Bulletin { } public float getBottomOffset() { - if (bulletin != null && bulletin.bottomOffsetSpring != null && bulletin.bottomOffsetSpring.isRunning()) { + if (bulletin != null && (delegate == null || delegate.bottomOffsetAnimated()) && bulletin.bottomOffsetSpring != null && bulletin.bottomOffsetSpring.isRunning()) { return bulletin.lastBottomOffset; } return delegate.getBottomOffset(bulletin != null ? bulletin.tag : 0); @@ -1445,7 +1445,7 @@ public class Bulletin { reactionsContainerLayout.setBubbleOffset(-AndroidUtilities.dp(80)); reactionsContainerLayout.setHint(LocaleController.getString(R.string.SavedTagReactionsHint)); addView(reactionsContainerLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL, 0, 36, 0, 0)); - reactionsContainerLayout.setMessage(null, null); + reactionsContainerLayout.setMessage(null, null, true); } @Override 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 808d1f9ba..ababf7886 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -42,6 +42,7 @@ import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.LaunchActivity; @@ -73,18 +74,19 @@ public final class BulletinFactory { if (baseFragment == null) { return BulletinFactory.of(Bulletin.BulletinWindow.make(ApplicationLoader.applicationContext), null); } + if (baseFragment.visibleDialog instanceof BottomSheet) { + return BulletinFactory.of(((BottomSheet) baseFragment.visibleDialog).container, baseFragment.getResourceProvider()); + } return BulletinFactory.of(baseFragment); } public void showForError(TLRPC.TL_error error) { - if (BuildVars.DEBUG_VERSION) { - createErrorBulletin(error.code + " " + error.text).show(); - } else { - createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); - } + if (!LaunchActivity.isActive) return; + createErrorBulletin(LocaleController.formatString(R.string.UnknownErrorCode, error.text)).show(); } public static void showError(TLRPC.TL_error error) { + if (!LaunchActivity.isActive) return; global().createErrorBulletin(LocaleController.formatString(R.string.UnknownErrorCode, error.text)).show(); } @@ -234,9 +236,9 @@ public final class BulletinFactory { } text = ssb; } - layout.textView.setText(text); layout.textView.setSingleLine(false); layout.textView.setMaxLines(maxLines); + layout.textView.setText(text); return create(layout, text.length() < 20 ? Bulletin.DURATION_SHORT : Bulletin.DURATION_LONG); } @@ -356,10 +358,27 @@ public final class BulletinFactory { } public Bulletin createUndoBulletin(CharSequence text, boolean textAndIcon, Runnable onUndo, Runnable onAction) { - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); - layout.textView.setText(text); - layout.textView.setSingleLine(false); - layout.textView.setMaxLines(2); + return this.createUndoBulletin(text, null, textAndIcon, onUndo, onAction); + } + + public Bulletin createUndoBulletin(CharSequence text, CharSequence subtitle, Runnable onUndo, Runnable onAction) { + return this.createUndoBulletin(text, subtitle, true, onUndo, onAction); + } + + public Bulletin createUndoBulletin(CharSequence text, CharSequence subtitle, boolean textAndIcon, Runnable onUndo, Runnable onAction) { + final Bulletin.ButtonLayout layout; + if (!TextUtils.isEmpty(subtitle)) { + final Bulletin.TwoLineLottieLayout twoLineLayout = new Bulletin.TwoLineLottieLayout(getContext(), resourcesProvider); + twoLineLayout.titleTextView.setText(text); + twoLineLayout.subtitleTextView.setText(subtitle); + layout = twoLineLayout; + } else { + final Bulletin.LottieLayout singleLineLayout = new Bulletin.LottieLayout(getContext(), resourcesProvider); + singleLineLayout.textView.setText(text); + singleLineLayout.textView.setSingleLine(false); + singleLineLayout.textView.setMaxLines(2); + layout = singleLineLayout; + } layout.setTimer(); layout.setButton(new Bulletin.UndoButton(getContext(), true, textAndIcon, resourcesProvider).setText(LocaleController.getString("Undo", R.string.Undo)).setUndoAction(onUndo).setDelayedAction(onAction)); return create(layout, Bulletin.DURATION_PROLONG); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java index 49e6efbbf..9ea2454a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java @@ -46,7 +46,7 @@ public class CacheChart extends View { private RectF chartBounds = new RectF(); private RectF chartInnerBounds = new RectF(); - private static final int DEFAULT_SECTIONS_COUNT = 10; + private static final int DEFAULT_SECTIONS_COUNT = 11; private static final int[] DEFAULT_COLORS = new int[] { Theme.key_statisticChartLine_lightblue, Theme.key_statisticChartLine_blue, @@ -57,6 +57,7 @@ public class CacheChart extends View { Theme.key_statisticChartLine_orange, Theme.key_statisticChartLine_cyan, Theme.key_statisticChartLine_purple, + Theme.key_statisticChartLine_golden, Theme.key_statisticChartLine_golden }; @@ -70,7 +71,8 @@ public class CacheChart extends View { R.raw.cache_stickers, R.raw.cache_profile_photos, R.raw.cache_other, - R.raw.cache_other + R.raw.cache_other, + R.raw.cache_documents }; private final int sectionsCount; 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 6a78edd34..fd3070d7f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -187,7 +187,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; -public class ChatActivityEnterView extends BlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate { +public class ChatActivityEnterView extends BlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate, SuggestEmojiView.AnchorViewDelegate { private int commonInputType; private boolean stickersEnabled; @@ -2467,7 +2467,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.audioRecordTooShort); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateBotMenuButton); @@ -5617,6 +5617,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return topView != null && topView.getVisibility() == VISIBLE; } + public float topViewVisible() { + return topViewEnterProgress; + } + public void onAdjustPanTransitionUpdate(float y, float progress, boolean keyboardVisible) { if (botWebViewMenuContainer != null) { botWebViewMenuContainer.setTranslationY(y); @@ -5717,7 +5721,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.sendingMessagesChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.audioRecordTooShort); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateBotMenuButton); @@ -5884,7 +5888,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.sendingMessagesChanged); currentAccount = account; accountInstance = AccountInstance.getInstance(currentAccount); @@ -5900,7 +5904,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged); } @@ -6726,7 +6730,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific editingMessageObject.editingMessage = message[0]; editingMessageObject.editingMessageEntities = entities; editingMessageObject.editingMessageSearchWebPage = messageWebPageSearch; - if (parentFragment != null && parentFragment.getCurrentChat() != null && !ChatObject.canSendEmbed(parentFragment.getCurrentChat())) { + if (parentFragment != null && parentFragment.getCurrentChat() != null && (editingMessageObject.type == MessageObject.TYPE_TEXT || editingMessageObject.type == MessageObject.TYPE_EMOJIS) && !ChatObject.canSendEmbed(parentFragment.getCurrentChat())) { editingMessageObject.editingMessageSearchWebPage = false; editingMessageObject.messageOwner.flags &=~ 512; editingMessageObject.messageOwner.media = null; @@ -10154,7 +10158,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } @Override - public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { + public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet, boolean edit) { if (trendingStickersAlert != null && !trendingStickersAlert.isDismissed()) { trendingStickersAlert.getLayout().showStickerSet(stickerSet, inputStickerSet); return; @@ -10171,7 +10175,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific inputStickerSet.access_hash = stickerSet.access_hash; inputStickerSet.id = stickerSet.id; } - fragment.showDialog(new StickersAlert(parentActivity, fragment, inputStickerSet, null, ChatActivityEnterView.this, resourcesProvider)); + StickersAlert alert = new StickersAlert(parentActivity, fragment, inputStickerSet, null, ChatActivityEnterView.this, resourcesProvider); + fragment.showDialog(alert); + if (edit) { + alert.enableEditMode(); + } } @Override @@ -11258,7 +11266,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (emojiButton != null) { emojiButton.invalidate(); } - } else if (id == NotificationCenter.messageReceivedByServer) { + } else if (id == NotificationCenter.messageReceivedByServer2) { Boolean scheduled = (Boolean) args[6]; if (scheduled) { return; 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 b197fa08a..3f83c98fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -21,6 +21,8 @@ import android.content.ContextWrapper; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Outline; @@ -91,6 +93,8 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -115,13 +119,17 @@ import org.telegram.ui.PassportActivity; import org.telegram.ui.PaymentFormActivity; import org.telegram.ui.PhotoPickerActivity; import org.telegram.ui.PhotoPickerSearchActivity; +import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; +import org.telegram.ui.Stories.recorder.StoryEntry; import org.telegram.ui.WebAppDisclaimerAlert; import org.telegram.ui.bots.BotWebViewContainer; import org.telegram.ui.bots.BotWebViewMenuContainer; import org.telegram.ui.bots.ChatAttachAlertBotWebViewLayout; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -136,6 +144,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public boolean forUser; public boolean isPhotoPicker; public boolean isStickerMode; + public Utilities.Callback2 customStickerHandler; private int currentLimit; private int codepointCount; @@ -826,6 +835,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N protected ActionBarMenuItem doneItem; protected FrameLayout headerView; protected TextView selectedTextView; + protected ActionBarMenuItem optionsItem; protected LinearLayout selectedView; protected ImageView selectedArrowImageView; protected LinearLayout mediaPreviewView; @@ -1372,7 +1382,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (isDismissed() || !openTransitionFinished) { return false; } - return !commentTextView.isPopupVisible(); + return currentAttachLayout != pollLayout && !commentTextView.isPopupVisible() || currentAttachLayout == pollLayout && !pollLayout.isPopupVisible(); } }; @@ -1450,12 +1460,22 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N ignoreLayout = false; } + if (pollLayout != null && keyboardSize <= AndroidUtilities.dp(20) && !pollLayout.isWaitingForKeyboardOpen() && !pollLayout.isPopupShowing() && !pollLayout.isAnimatePopupClosing()) { + ignoreLayout = true; + pollLayout.hideEmojiView(); + ignoreLayout = false; + } + if (keyboardSize <= AndroidUtilities.dp(20)) { int paddingBottom; if (keyboardVisible) { paddingBottom = 0; } else { - paddingBottom = commentTextView.getEmojiPadding(); + if (currentAttachLayout == pollLayout && pollLayout.emojiView != null) { + paddingBottom = pollLayout.getEmojiPadding(); + } else { + paddingBottom = commentTextView.getEmojiPadding(); + } } if (!AndroidUtilities.isInMultiwindow) { heightSize -= paddingBottom; @@ -1475,7 +1495,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (child == null || child.getVisibility() == GONE) { continue; } - if (commentTextView != null && commentTextView.isPopupView(child)) { + if (commentTextView != null && commentTextView.isPopupView(child) || pollLayout != null && child == pollLayout.emojiView) { if (inBubbleMode) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize + getPaddingTop(), MeasureSpec.EXACTLY)); } else if (AndroidUtilities.isInMultiwindow || AndroidUtilities.isTablet()) { @@ -1513,7 +1533,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (keyboardVisible) { paddingBottom += 0; } else { - paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0; + if (pollLayout != null && currentAttachLayout == pollLayout && pollLayout.emojiView != null) { + paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? pollLayout.getEmojiPadding() : 0; + } else { + paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0; + } } setBottomClip(paddingBottom); @@ -1564,7 +1588,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N childTop = lp.topMargin; } - if (commentTextView != null && commentTextView.isPopupView(child)) { + if (commentTextView != null && commentTextView.isPopupView(child) || pollLayout != null && child == pollLayout.emojiView) { if (AndroidUtilities.isTablet()) { childTop = getMeasuredHeight() - child.getMeasuredHeight(); } else { @@ -2084,6 +2108,68 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }); } + optionsItem = new ActionBarMenuItem(context, null, 0, getThemedColor(Theme.key_dialogTextBlack), false, resourcesProvider); + optionsItem.setLongClickEnabled(false); + optionsItem.setIcon(R.drawable.ic_ab_other); + optionsItem.setContentDescription(LocaleController.getString(R.string.AccDescrMoreOptions)); + optionsItem.setVisibility(View.GONE); + optionsItem.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), Theme.RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE)); + optionsItem.addSubItem(1, R.drawable.msg_addbot, LocaleController.getString(R.string.StickerCreateEmpty)).setOnClickListener(v -> { + optionsItem.toggleSubMenu(); + PhotoViewer.getInstance().setParentActivity(baseFragment, resourcesProvider); + PhotoViewer.getInstance().setParentAlert(this); + PhotoViewer.getInstance().setMaxSelectedPhotos(maxSelectedPhotos, allowOrder); + if (!delegate.needEnterComment()) { + AndroidUtilities.hideKeyboard(baseFragment.getFragmentView().findFocus()); + AndroidUtilities.hideKeyboard(getContainer().findFocus()); + } + File file = StoryEntry.makeCacheFile(currentAccount, "webp"); + int w = AndroidUtilities.displaySize.x, h = AndroidUtilities.displaySize.y; + if (w > 1080 || h > 1080) { + float scale = Math.min(w, h) / 1080f; + w = (int) (w * scale); + h = (int) (h * scale); + } + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + try { + b.compress(Bitmap.CompressFormat.WEBP, 100, new FileOutputStream(file)); + } catch (Throwable e) { + FileLog.e(e); + } + b.recycle(); + + ArrayList arrayList = new ArrayList<>(); + final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); + arrayList.add(entry); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public boolean allowCaption() { + return false; + } + @Override + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + sent = true; + if (delegate == null) { + return; + } + entry.editedInfo = videoEditedInfo; + ChatAttachAlertPhotoLayout.selectedPhotosOrder.clear(); + ChatAttachAlertPhotoLayout.selectedPhotos.clear(); + ChatAttachAlertPhotoLayout.selectedPhotosOrder.add(0); + ChatAttachAlertPhotoLayout.selectedPhotos.put(0, entry); + delegate.didPressedButton(7, true, notify, scheduleDate, forceDocument); + } + }, baseFragment instanceof ChatActivity ? (ChatActivity) baseFragment : null); + if (isStickerMode) { + PhotoViewer.getInstance().enableStickerMode(null, true, customStickerHandler); + } + }); + optionsItem.setMenuYOffset(AndroidUtilities.dp(-12)); + optionsItem.setAdditionalXOffset(AndroidUtilities.dp(12)); + optionsItem.setOnClickListener(v -> { + optionsItem.toggleSubMenu(); + }); + headerView = new FrameLayout(context) { @Override public void setAlpha(float alpha) { @@ -2121,7 +2207,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N selectedTextView = new TextView(context); selectedTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); selectedTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - selectedTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + selectedTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); selectedTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); selectedTextView.setMaxLines(1); selectedTextView.setEllipsize(TextUtils.TruncateAt.END); @@ -2166,12 +2252,15 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N containerView.addView(photoLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - containerView.addView(headerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 23, 0, 48, 0)); + containerView.addView(headerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 23, 0, 12, 0)); containerView.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); containerView.addView(selectedMenuItem, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.RIGHT)); if (searchItem != null) { containerView.addView(searchItem, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.RIGHT)); } + if (optionsItem != null) { + headerView.addView(optionsItem, LayoutHelper.createFrame(32, 32, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 0, 0, 8)); + } containerView.addView(doneItem, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 48, Gravity.TOP | Gravity.RIGHT)); actionBarShadow = new View(context); @@ -4330,7 +4419,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N @Override public void onOpenAnimationStart() { - + sent = false; } @Override @@ -4338,10 +4427,18 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N return true; } + private boolean allowDrawContent = true; + public boolean sent = false; @Override public void setAllowDrawContent(boolean value) { super.setAllowDrawContent(value); currentAttachLayout.onContainerTranslationUpdated(currentPanTranslationY); + if (allowDrawContent != value) { + allowDrawContent = value; + if (currentAttachLayout == photoLayout && photoLayout != null && !photoLayout.cameraExpanded) { + photoLayout.pauseCamera(!allowDrawContent || sent); + } + } } public void setStories(boolean value) { @@ -4370,7 +4467,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } } - public void enableStickerMode() { + public void enableStickerMode(Utilities.Callback2 customStickerHandler) { selectedTextView.setText(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto)); typeButtonsAvailable = false; buttonsRecyclerView.setVisibility(View.GONE); @@ -4378,6 +4475,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N avatarPicker = 1; isPhotoPicker = true; isStickerMode = true; + this.customStickerHandler = customStickerHandler; + if (optionsItem != null) { + selectedTextView.setTranslationY(-AndroidUtilities.dp(8)); + optionsItem.setVisibility(View.VISIBLE); + } } public void enableDefaultMode() { @@ -4387,6 +4489,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N avatarPicker = 0; isPhotoPicker = false; isStickerMode = false; + customStickerHandler = null; + if (optionsItem != null) { + selectedTextView.setTranslationY(0); + optionsItem.setVisibility(View.GONE); + } } public TextView getSelectedTextView() { 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 7c2246ff1..4a2ca1ad4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java @@ -1187,7 +1187,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa if (DialogObject.isUserDialog(dialogId)) { user = parentAlert.baseFragment.getMessagesController().getUser(dialogId); } - AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> { + AlertsCreator.createLocationUpdateDialog(getParentActivity(), false, user, param -> { TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); location.geo = new TLRPC.TL_geoPoint(); location.geo.lat = AndroidUtilities.fixLocationCoord(myLocation.getLatitude()); 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 fe5313eaf..8c222ee66 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -155,7 +155,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou private float cameraViewOffsetX; private float cameraViewOffsetY; private float cameraViewOffsetBottomY; - private boolean cameraOpened; + public boolean cameraOpened; private boolean canSaveCameraPreview; private boolean cameraAnimationInProgress; private float cameraOpenProgress; @@ -176,8 +176,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou private boolean takingPhoto; private static boolean mediaFromExternalCamera; private static ArrayList cameraPhotos = new ArrayList<>(); - private static HashMap selectedPhotos = new HashMap<>(); - private static ArrayList selectedPhotosOrder = new ArrayList<>(); + public static HashMap selectedPhotos = new HashMap<>(); + public static ArrayList selectedPhotosOrder = new ArrayList<>(); public static int lastImageId = -1; private boolean cancelTakingPhotos; private boolean checkCameraWhenShown; @@ -349,7 +349,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } } - private PhotoViewer.PhotoViewerProvider photoViewerProvider = new BasePhotoProvider() { + public PhotoViewer.PhotoViewerProvider photoViewerProvider = new BasePhotoProvider() { @Override public void onOpen() { pauseCameraPreview(); @@ -473,6 +473,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + parentAlert.sent = true; MediaController.PhotoEntry photoEntry = getPhotoEntryAtPosition(index); if (photoEntry != null) { photoEntry.editedInfo = videoEditedInfo; @@ -808,7 +809,11 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou int type; if (parentAlert.isPhotoPicker && parentAlert.isStickerMode) { type = PhotoViewer.SELECT_TYPE_STICKER; - chatActivity = (ChatActivity) parentAlert.baseFragment; + if (parentAlert.baseFragment instanceof ChatActivity) { + chatActivity = (ChatActivity) parentAlert.baseFragment; + } else { + chatActivity = null; + } } else if (parentAlert.avatarPicker != 0) { chatActivity = null; type = PhotoViewer.SELECT_TYPE_AVATAR; @@ -871,7 +876,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou PhotoViewer.getInstance().closePhotoAfterSelect = false; } if (parentAlert.isStickerMode) { - PhotoViewer.getInstance().enableStickerMode(null); + PhotoViewer.getInstance().enableStickerMode(null, false, parentAlert.customStickerHandler); } if (captionForAllMedia()) { PhotoViewer.getInstance().setCaption(parentAlert.getCommentTextView().getText()); @@ -1069,6 +1074,9 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou if (parentAlert.avatarPicker != 2 && !(parentAlert.baseFragment instanceof ChatActivity) || takingPhoto || parentAlert.destroyed || cameraView == null) { return false; } + if (parentAlert.isStickerMode) { + return false; + } BaseFragment baseFragment = parentAlert.baseFragment; if (baseFragment == null) { baseFragment = LaunchActivity.getLastFragment(); @@ -1891,6 +1899,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + parentAlert.sent = true; if (cameraPhotos.isEmpty() || parentAlert.destroyed) { return; } @@ -1957,7 +1966,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou }, chatActivity); PhotoViewer.getInstance().setAvatarFor(parentAlert.getAvatarFor()); if (parentAlert.isStickerMode) { - PhotoViewer.getInstance().enableStickerMode(null); + PhotoViewer.getInstance().enableStickerMode(null, false, parentAlert.customStickerHandler); PhotoViewer.getInstance().prepareSegmentImage(); } } @@ -2795,6 +2804,9 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } protected void checkCameraViewPosition() { + if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().stickerMakerView != null && PhotoViewer.getInstance().stickerMakerView.isThanosInProgress) { + return; + } if (Build.VERSION.SDK_INT >= 21) { if (cameraView != null) { cameraView.invalidateOutline(); @@ -3588,18 +3600,36 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } private void onPhotoEditModeChanged(boolean isEditMode) { +// if (needCamera && !noCameraPermissions) { +// if (isEditMode) { +// if (cameraView != null) { +// isCameraFrontfaceBeforeEnteringEditMode = cameraView.isFrontface(); +// hideCamera(true); +// } +// } else { +// afterCameraInitRunnable = () -> { +// pauseCameraPreview(); +// afterCameraInitRunnable = null; +// isCameraFrontfaceBeforeEnteringEditMode = null; +// }; +// showCamera(); +// } +// } + } + + public void pauseCamera(boolean pause) { if (needCamera && !noCameraPermissions) { - if (isEditMode) { + if (pause) { if (cameraView != null) { isCameraFrontfaceBeforeEnteringEditMode = cameraView.isFrontface(); hideCamera(true); } } else { - afterCameraInitRunnable = () -> { - pauseCameraPreview(); - afterCameraInitRunnable = null; - isCameraFrontfaceBeforeEnteringEditMode = null; - }; +// afterCameraInitRunnable = () -> { +// pauseCameraPreview(); +// afterCameraInitRunnable = null; +// isCameraFrontfaceBeforeEnteringEditMode = null; +// }; showCamera(); } } @@ -3881,7 +3911,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } else { galleryAlbumEntry = MediaController.allPhotosAlbumEntry; } - if (selectedAlbumEntry == null) { + if (selectedAlbumEntry == null || parentAlert != null && parentAlert.isStickerMode) { selectedAlbumEntry = galleryAlbumEntry; } else if (shouldLoadAllMedia()) { for (int a = 0; a < MediaController.allMediaAlbums.size(); a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java index 2e7deeff5..445632e0f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java @@ -1,5 +1,10 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -8,8 +13,11 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.text.Editable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.ImageSpan; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; @@ -17,16 +25,24 @@ import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; +import android.widget.FrameLayout; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; @@ -38,6 +54,7 @@ import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Stories.recorder.KeyboardNotifier; import java.util.ArrayList; import java.util.Arrays; @@ -50,18 +67,24 @@ import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; -public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout { +public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout implements SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; private RecyclerListView listView; private SimpleItemAnimator itemAnimator; private FillLastLinearLayoutManager layoutManager; + private SuggestEmojiView suggestEmojiPanel; private HintView hintView; + public EmojiView emojiView; + private KeyboardNotifier keyboardNotifier; + private boolean waitingForKeyboardOpen; + private boolean destroyed; + private boolean isPremium; - private String[] answers = new String[10]; + private CharSequence[] answers = new CharSequence[10]; private boolean[] answersChecks = new boolean[10]; private int answersCount = 1; - private String questionString; + private CharSequence questionString; private CharSequence solutionString; private boolean anonymousPoll = true; private boolean multipleChoise; @@ -167,15 +190,31 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout } } + private final Runnable openKeyboardRunnable = new Runnable() { + @Override + public void run() { + if (currentCell != null) { + EditTextBoldCursor editText = currentCell.getEditField(); + if (!destroyed && editText != null && waitingForKeyboardOpen && !keyboardVisible && !AndroidUtilities.usingHardwareInput && !AndroidUtilities.isInMultiwindow && AndroidUtilities.isTablet()) { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + } + }; + public ChatAttachAlertPollLayout(ChatAttachAlert alert, Context context, Theme.ResourcesProvider resourcesProvider) { super(alert, context, resourcesProvider); updateRows(); - + isPremium = AccountInstance.getInstance(parentAlert.currentAccount).getUserConfig().isPremium(); /*if (quiz != null) { quizPoll = quiz; quizOnly = quizPoll ? 1 : 2; }*/ + parentAlert.sizeNotifierFrameLayout.setDelegate(this); listAdapter = new ListAdapter(context); listView = new RecyclerListView(context) { @@ -255,6 +294,9 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout TextCheckCell cell = (TextCheckCell) view; boolean checked; boolean wasChecksBefore = quizPoll; + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } if (position == anonymousRow) { checked = anonymousPoll = !anonymousPoll; } else if (position == multipleRow) { @@ -332,6 +374,28 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { parentAlert.updateLayout(ChatAttachAlertPollLayout.this, true, dy); + if (suggestEmojiPanel != null && suggestEmojiPanel.isShown()) { + SuggestEmojiView.AnchorViewDelegate emojiDelegate = suggestEmojiPanel.getDelegate(); + if (emojiDelegate instanceof PollEditTextCell) { + PollEditTextCell cell = (PollEditTextCell) emojiDelegate; + RecyclerView.ViewHolder holder = listView.findContainingViewHolder(cell); + if (holder != null) { + int position = holder.getAdapterPosition(); + if (suggestEmojiPanel.getDirection() == SuggestEmojiView.DIRECTION_TO_BOTTOM) { + suggestEmojiPanel.setTranslationY(holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight()); + } else { + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + if (position < layoutManager.findFirstVisibleItemPosition() || position > layoutManager.findLastVisibleItemPosition()) { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } if (dy != 0 && hintView != null) { hintView.hide(); } @@ -359,6 +423,20 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout hintView.setVisibility(View.INVISIBLE); addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); + if (isPremium) { + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + suggestEmojiPanel = new SuggestEmojiView(context, parentAlert.currentAccount, null, resourcesProvider) { + @Override + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + } + }; + suggestEmojiPanel.forbidCopy(); + suggestEmojiPanel.forbidSetAsStatus(); + suggestEmojiPanel.setHorizontalPadding(AndroidUtilities.dp(24)); + addView(suggestEmojiPanel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 160, Gravity.LEFT | Gravity.TOP)); + } + keyboardNotifier = new KeyboardNotifier(parentAlert.sizeNotifierFrameLayout, null); checkDoneButton(); } @@ -368,10 +446,17 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout } @Override - public void onResume() { + public void onPause() { + super.onPause(); if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + if (isPremium) { + hideEmojiPopup(false); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + } } @Override @@ -394,19 +479,47 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout } return; } + + CharSequence questionText = getFixedString(questionString); + CharSequence[] questionCharSequence = new CharSequence[]{ questionText }; + ArrayList questionEntities = MediaDataController.getInstance(parentAlert.currentAccount).getEntities(questionCharSequence, true); + questionText = questionCharSequence[0]; + for (int a = 0, N = questionEntities.size(); a < N; a++) { + TLRPC.MessageEntity entity = questionEntities.get(a); + if (entity.offset + entity.length > questionText.length()) { + entity.length = questionText.length() - entity.offset; + } + } + TLRPC.TL_messageMediaPoll poll = new TLRPC.TL_messageMediaPoll(); poll.poll = new TLRPC.TL_poll(); poll.poll.multiple_choice = multipleChoise; poll.poll.quiz = quizPoll; poll.poll.public_voters = !anonymousPoll; - poll.poll.question = getFixedString(questionString).toString(); + poll.poll.question = new TLRPC.TL_textWithEntities(); + poll.poll.question.text = questionText.toString(); + poll.poll.question.entities = questionEntities; + SerializedData serializedData = new SerializedData(10); for (int a = 0; a < answers.length; a++) { if (TextUtils.isEmpty(getFixedString(answers[a]))) { continue; } - TLRPC.TL_pollAnswer answer = new TLRPC.TL_pollAnswer(); - answer.text = getFixedString(answers[a]).toString(); + CharSequence answerText = getFixedString(answers[a]); + CharSequence[] answerCharSequence = new CharSequence[]{ answerText }; + ArrayList answerEntities = MediaDataController.getInstance(parentAlert.currentAccount).getEntities(answerCharSequence, true); + answerText = answerCharSequence[0]; + for (int b = 0, N = answerEntities.size(); b < N; b++) { + TLRPC.MessageEntity entity = answerEntities.get(b); + if (entity.offset + entity.length > answerText.length()) { + entity.length = answerText.length() - entity.offset; + } + } + + TLRPC.PollAnswer answer = new TLRPC.TL_pollAnswer(); + answer.text = new TLRPC.TL_textWithEntities(); + answer.text.text = answerText.toString(); + answer.text.entities = answerEntities; answer.option = new byte[1]; answer.option[0] = (byte) (48 + poll.poll.answers.size()); poll.poll.answers.add(answer); @@ -479,7 +592,7 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout @Override public void onPreMeasure(int availableWidth, int availableHeight) { int padding; - if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) { + if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20) || emojiViewVisible || isAnimatePopupClosing) { padding = AndroidUtilities.dp(52); parentAlert.setAllowNestedScroll(false); } else { @@ -521,6 +634,20 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout listView.smoothScrollToPosition(1); } + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + if (emojiView != null) { + emojiView.invalidateViews(); + } + if (currentCell != null) { + int color = currentCell.getEditField().getCurrentTextColor(); + currentCell.getEditField().setTextColor(0xffffffff); + currentCell.getEditField().setTextColor(color); + } + } + } + public static CharSequence getFixedString(CharSequence text) { if (TextUtils.isEmpty(text)) { return text; @@ -536,12 +663,14 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout } private void showQuizHint() { - int count = listView.getChildCount(); for (int a = answerStartRow; a < answerStartRow + answersCount; a++) { RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(a); if (holder != null && holder.itemView instanceof PollEditTextCell) { PollEditTextCell pollEditTextCell = (PollEditTextCell) holder.itemView; if (pollEditTextCell.getTop() > AndroidUtilities.dp(40)) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } hintView.showForView(pollEditTextCell.getCheckBox(), true); break; } @@ -651,6 +780,18 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout layoutManager.scrollToPositionWithOffset(0, 0); } + @Override + public void onDestroy() { + super.onDestroy(); + destroyed = true; + if (isPremium) { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + if (emojiView != null) { + parentAlert.sizeNotifierFrameLayout.removeView(emojiView); + } + } + } + @Override public void onHidden() { parentAlert.doneItem.setVisibility(INVISIBLE); @@ -658,6 +799,10 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout @Override public boolean onBackPressed() { + if (emojiViewVisible) { + hideEmojiPopup(true); + return true; + } if (!checkDiscard()) { return true; } @@ -721,6 +866,11 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout } private void addNewField() { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + resetSuggestEmojiPanel(); listView.setItemAnimator(itemAnimator); answersChecks[answersCount] = false; answersCount++; @@ -734,6 +884,349 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout listAdapter.notifyItemChanged(emptyRow); } + private void updateSuggestEmojiPanelDelegate(RecyclerView.ViewHolder holder) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + if (suggestEmojiPanel != null && holder != null && holder.itemView instanceof PollEditTextCell && suggestEmojiPanel.getDelegate() != holder.itemView) { + suggestEmojiPanel.setDelegate((PollEditTextCell) holder.itemView); + } + } + } + + private void resetSuggestEmojiPanel() { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.setDelegate(null); + suggestEmojiPanel.forceClose(); + } + } + + private int lastSizeChangeValue1; + private boolean lastSizeChangeValue2; + + @Override + public void onSizeChanged(int height, boolean isWidthGreater) { + if (!isPremium) { + return; + } + if (height > dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + if (isWidthGreater) { + keyboardHeightLand = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height_land3", keyboardHeightLand).commit(); + } else { + keyboardHeight = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height", keyboardHeight).commit(); + } + } + + if (emojiViewVisible) { + int newHeight = (isWidthGreater ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) emojiView.getLayoutParams(); + if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { + layoutParams.width = AndroidUtilities.displaySize.x; + layoutParams.height = newHeight; + emojiView.setLayoutParams(layoutParams); + emojiPadding = layoutParams.height; + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + } + } + + if (lastSizeChangeValue1 == height && lastSizeChangeValue2 == isWidthGreater) { + return; + } + lastSizeChangeValue1 = height; + lastSizeChangeValue2 = isWidthGreater; + + boolean oldValue = keyboardVisible; + if (currentCell != null) { + final EditTextBoldCursor editText = currentCell.getEditField(); + keyboardVisible = editText.isFocused() && keyboardNotifier.keyboardVisible() && height > 0; + } else { + keyboardVisible = false; + } + if (keyboardVisible && emojiViewVisible) { + showEmojiPopup(0); + } + if (emojiPadding != 0 && !keyboardVisible && keyboardVisible != oldValue && !emojiViewVisible) { + emojiPadding = 0; + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + } + + if (keyboardVisible && waitingForKeyboardOpen) { + waitingForKeyboardOpen = false; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + } + } + + public boolean isWaitingForKeyboardOpen() { + return waitingForKeyboardOpen; + } + + public boolean emojiViewVisible, emojiViewWasVisible; + private int emojiPadding; + private int keyboardHeight, keyboardHeightLand; + private boolean keyboardVisible, isAnimatePopupClosing; + private PollEditTextCell currentCell; + + private void onEmojiClicked(PollEditTextCell cell) { + this.currentCell = cell; + if (emojiViewVisible) { + openKeyboardInternal(); + } else { + showEmojiPopup(1); + } + } + + private void openKeyboardInternal() { + keyboardNotifier.awaitKeyboard(); + final EditTextBoldCursor editText = currentCell.getEditField(); + AndroidUtilities.showKeyboard(editText); + showEmojiPopup(AndroidUtilities.usingHardwareInput ? 0 : 2); + + if (!AndroidUtilities.usingHardwareInput && !keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + waitingForKeyboardOpen = true; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + + private void showEmojiPopup(int show) { + if (!isPremium) { + return; + } + if (show == 1) { + boolean emojiWasVisible = emojiView != null && emojiView.getVisibility() == View.VISIBLE; + createEmojiView(); + + emojiView.setVisibility(VISIBLE); + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = true; + View currentView = emojiView; + + if (keyboardHeight <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeight = dp(150); + } else { + keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", dp(200)); + } + } + if (keyboardHeightLand <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeightLand = dp(150); + } else { + keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", dp(200)); + } + } + int currentHeight = (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) currentView.getLayoutParams(); + layoutParams.height = currentHeight; + currentView.setLayoutParams(layoutParams); + if (!AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() && currentCell != null) { + AndroidUtilities.hideKeyboard(currentCell.getEditField()); + } + + emojiPadding = currentHeight; + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.KEYBOARD, true); + } + if (!emojiWasVisible && !keyboardVisible) { + ValueAnimator animator = ValueAnimator.ofFloat(emojiPadding, 0); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + emojiView.setTranslationY(0); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } + } else { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, true); + } + if (emojiView != null) { + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = false; + if (AndroidUtilities.usingHardwareInput || AndroidUtilities.isInMultiwindow) { + emojiView.setVisibility(GONE); + } + } + if (show == 0) { + emojiPadding = 0; + } + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + } + } + + private void hideEmojiPopup(boolean byBackButton) { + if (!isPremium) { + return; + } + if (emojiViewVisible) { + showEmojiPopup(0); + } + if (byBackButton) { + if (emojiView != null && emojiView.getVisibility() == View.VISIBLE) { + int height = emojiView.getMeasuredHeight(); + ValueAnimator animator = ValueAnimator.ofFloat(0, height); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + isAnimatePopupClosing = true; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimatePopupClosing = false; + emojiView.setTranslationY(0); + hideEmojiView(); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } else { + hideEmojiView(); + } + } + } + + public void hideEmojiView() { + if (!emojiViewVisible && emojiView != null && emojiView.getVisibility() != GONE) { + if (currentCell != null) { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } + } + emojiView.setVisibility(GONE); + } + int wasEmojiPadding = emojiPadding; + emojiPadding = 0; + if (wasEmojiPadding != emojiPadding) { + keyboardNotifier.fire(); + } + } + + public boolean isAnimatePopupClosing() { + return isAnimatePopupClosing; + } + + public boolean isPopupShowing() { + return emojiViewVisible; + } + + public boolean isPopupVisible() { + return emojiView != null && emojiView.getVisibility() == View.VISIBLE; + } + + public int getEmojiPadding() { + return emojiPadding; + } + + private void createEmojiView() { + if (emojiView != null && emojiView.currentAccount != UserConfig.selectedAccount) { + parentAlert.sizeNotifierFrameLayout.removeView(emojiView); + emojiView = null; + } + if (emojiView != null) { + return; + } + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider, false); + emojiView.emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + emojiView.fixBottomTabContainerTranslation = false; + emojiView.allowEmojisForNonPremium(false); + emojiView.setVisibility(GONE); + if (AndroidUtilities.isTablet()) { + emojiView.setForseMultiwindowLayout(true); + } + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { + @Override + public boolean onBackspace() { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return false; + } + editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + return true; + } + + @Override + public void onEmojiSelected(String symbol) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, editText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + editText.setText(editText.getText().insert(i, localCharSequence)); + int j = i + localCharSequence.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onCustomEmojiSelected(long documentId, TLRPC.Document document, String emoticon, boolean isRecent) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + SpannableString spannable = new SpannableString(emoticon); + AnimatedEmojiSpan span; + if (document != null) { + span = new AnimatedEmojiSpan(document, editText.getPaint().getFontMetricsInt()); + } else { + span = new AnimatedEmojiSpan(documentId, editText.getPaint().getFontMetricsInt()); + } + span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editText.setText(editText.getText().insert(i, spannable)); + int j = i + spannable.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onClearEmojiRecent() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourcesProvider); + builder.setTitle(LocaleController.getString("ClearRecentEmojiTitle", R.string.ClearRecentEmojiTitle)); + builder.setMessage(LocaleController.getString("ClearRecentEmojiText", R.string.ClearRecentEmojiText)); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.show(); + } + }); + parentAlert.sizeNotifierFrameLayout.addView(emojiView); + } + + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -855,10 +1348,17 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout @Override public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() == 4) { + if (holder.getItemViewType() == 4 || holder.getItemViewType() == 5) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; EditTextBoldCursor editText = editTextCell.getTextView(); if (editText.isFocused()) { + if (isPremium) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + hideEmojiPopup(true); + } + currentCell = null; editText.clearFocus(); AndroidUtilities.hideKeyboard(editText); } @@ -892,10 +1392,36 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout view = new TextCell(mContext); break; case 4: { - PollEditTextCell cell = new PollEditTextCell(mContext, null) { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { @Override protected void onFieldTouchUp(EditTextBoldCursor editText) { parentAlert.makeFocusable(editText, true); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } + + @Override + protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionMode) { + if (editText.isFocused() && editText.hasSelection()) { + Menu menu = actionMode.getMenu(); + if (menu.findItem(android.R.id.copy) == null) { + return; + } + ChatActivity.fillActionModeMenu(menu, ((ChatActivity) parentAlert.baseFragment).getCurrentEncryptedChat(), true); + } + } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); } }; cell.createErrorTextView(); @@ -915,8 +1441,22 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout if (cell.getTag() != null) { return; } - questionString = s.toString(); RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } + questionString = s; if (holder != null) { setTextLeft(holder.itemView, questionRow); } @@ -930,10 +1470,20 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout view = new TextCheckCell(mContext); break; case 7: { - PollEditTextCell cell = new PollEditTextCell(mContext, true, null) { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { @Override protected void onFieldTouchUp(EditTextBoldCursor editText) { parentAlert.makeFocusable(editText, true); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } } @Override @@ -946,6 +1496,11 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout ChatActivity.fillActionModeMenu(menu, ((ChatActivity) parentAlert.baseFragment).getCurrentEncryptedChat(), true); } } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } }; cell.createErrorTextView(); cell.addTextWatcher(new TextWatcher() { @@ -964,8 +1519,22 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout if (cell.getTag() != null) { return; } + RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } solutionString = s; - RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(solutionRow); if (holder != null) { setTextLeft(holder.itemView, solutionRow); } @@ -990,7 +1559,7 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout break; } default: { - PollEditTextCell cell = new PollEditTextCell(mContext, v -> { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, v -> { if (v.getTag() != null) { return; } @@ -1016,12 +1585,26 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout if (holder != null && holder.itemView instanceof PollEditTextCell) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; editTextCell.getTextView().requestFocus(); + if (isPremium) { + editTextCell.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } } else if (editText.isFocused()) { AndroidUtilities.hideKeyboard(editText); } + if (isPremium) { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } editText.clearFocus(); checkDoneButton(); updateRows(); + hideEmojiPopup(false); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + suggestEmojiPanel.setDelegate(null); + } listAdapter.notifyItemChanged(answerSectionRow); listAdapter.notifyItemChanged(emptyRow); } @@ -1047,6 +1630,16 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout @Override protected void onFieldTouchUp(EditTextBoldCursor editText) { parentAlert.makeFocusable(editText, true); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } } @Override @@ -1086,6 +1679,11 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout } return false; } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } }; cell.addTextWatcher(new TextWatcher() { @Override @@ -1107,7 +1705,25 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout if (index < 0 || index >= answers.length) { return; } - answers[index] = s.toString(); + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + float y = holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight(); + if (y > 0) { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_BOTTOM); + suggestEmojiPanel.setTranslationY(y); + } else { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.fireUpdate(); + } + + answers[index] = s; setTextLeft(cell, position); checkDoneButton(); } @@ -1189,7 +1805,7 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout if (idx1 < 0 || idx2 < 0 || idx1 >= answersCount || idx2 >= answersCount) { return; } - String from = answers[idx1]; + CharSequence from = answers[idx1]; answers[idx1] = answers[idx2]; answers[idx2] = from; boolean temp = answersChecks[idx1]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java index 9e133f223..ea75dffaa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java @@ -271,6 +271,15 @@ public class ChatGreetingsView extends LinearLayout { }); } + public void setSticker(String stickerPath) { + if (stickerPath == null) { + return; + } + wasDraw = true; + nextStickerToSendView.clearImage(); + stickerToSendView.setImage(ImageLocation.getForPath(stickerPath), "256_256", null, null, 0, null); + } + public void setNextSticker(TLRPC.Document sticker, Runnable whenDone) { if (sticker == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java index e8fbf67d6..b092b8d5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java @@ -19,13 +19,13 @@ import org.telegram.ui.ActionBar.Theme; public class ColoredImageSpan extends ReplacementSpan { int drawableColor; - Drawable drawable; + public Drawable drawable; boolean usePaintColor = true; public boolean useLinkPaintColor = false; int colorKey; private int topOffset = 0; - private float translateX, translateY; + private float translateX, translateY, rotate; private float alpha = 1f; private int overrideColor; @@ -91,6 +91,10 @@ public class ColoredImageSpan extends ReplacementSpan { translateY = ty; } + public void rotate(float r) { + rotate = r; + } + public void setWidth(int width) { sizeWidth = width; } @@ -108,7 +112,7 @@ public class ColoredImageSpan extends ReplacementSpan { fm.top = fontMetrics.top; fm.bottom = fontMetrics.bottom; } - return (int) (scaleX * Math.abs(spaceScaleX) * size); + return (int) (Math.abs(scaleX) * Math.abs(spaceScaleX) * size); } if (sizeWidth != 0) return (int) (Math.abs(scaleX) * sizeWidth); @@ -153,6 +157,9 @@ public class ColoredImageSpan extends ReplacementSpan { if (scaleX != 1f || scaleY != 1f) { canvas.scale(scaleX, scaleY, 0, drawable.getBounds().centerY()); } + if (rotate != 1f) { + canvas.rotate(rotate, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } if (alpha != 1f || paint.getAlpha() != 0xFF) { drawable.setAlpha((int) (alpha * paint.getAlpha())); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java index f7a6cf29c..f54d5ed23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java @@ -11,6 +11,7 @@ package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; @@ -25,6 +26,7 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback { private int iconHeight; private int backWidth; private int backHeight; + private boolean center; private int offsetX; private int offsetY; private boolean fullSize; @@ -77,6 +79,10 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback { backHeight = height; } + public void setCenter(boolean value) { + center = value; + } + public void setIconOffset(int x, int y) { offsetX = x; offsetY = y; @@ -135,6 +141,15 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback { @Override public void draw(Canvas canvas) { + if (center) { + Rect bounds = getBounds(); + setBounds( + bounds.centerX() - getIntrinsicWidth() / 2, + bounds.centerY() - getIntrinsicHeight() / 2, + bounds.centerX() + getIntrinsicWidth() / 2, + bounds.centerY() + getIntrinsicHeight() / 2 + ); + } if (background != null) { background.setBounds(getBounds()); background.draw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java index 55e57800e..4a67301fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java @@ -432,10 +432,12 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen public void reset(boolean force) { areaView.resetAnimator(); - areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), state.getBaseRotation() % 180 != 0, freeform); + areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), state != null && state.getBaseRotation() % 180 != 0, freeform); areaView.setLockedAspectRatio(freeform ? 0.0f : 1.0f); - state.reset(areaView, 0, freeform); - state.mirrored = false; + if (state != null) { + state.reset(areaView, 0, freeform); + state.mirrored = false; + } areaView.getCropRect(initialAreaRect); updateMatrix(force); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java new file mode 100644 index 000000000..102c9b490 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java @@ -0,0 +1,928 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.formatPluralString; +import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_EXPANDABLE_SWITCH; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_SHADOW_COLLAPSE_BUTTON; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_SWITCH; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_USER_GROUP_CHECKBOX; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_USER_CHECKBOX; + +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BotWebViewVibrationEffect; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.stream.Collectors; + +public class DeleteMessagesBottomSheet extends BottomSheetWithRecyclerListView { + private UniversalAdapter adapter; + + private SelectorBtnCell buttonContainer; + private TextView actionButton; + + private TLRPC.Chat inChat; + private boolean isForum; + private ArrayList messages; + private long mergeDialogId; + private int topicId; + private int mode; + private Runnable onDelete; + + private boolean restrict = false; + + private static final int ACTION_REPORT = 0; + private static final int ACTION_DELETE_ALL = 1; + private static final int ACTION_BAN = 2; + + private Action report; + private Action deleteAll; + private Action banOrRestrict; + + private boolean[] banFilter; + private boolean[] restrictFilter; + private boolean canRestrict; + + private TLRPC.TL_chatBannedRights defaultBannedRights; + private TLRPC.TL_chatBannedRights bannedRights; + private ArrayList participantsBannedRights; + private boolean sendMediaCollapsed = true; + + private static final int RIGHT_SEND_MESSAGES = 0; + private static final int RIGHT_SEND_MEDIA = 1; + private static final int RIGHT_ADD_USERS = 2; + private static final int RIGHT_PIN_MESSAGES = 3; + private static final int RIGHT_CHANGE_CHAT_INFO = 4; + private static final int RIGHT_CREATE_TOPICS = 5; + private static final int RIGHT_SEND_PHOTOS = 6; + private static final int RIGHT_SEND_VIDEOS = 7; + private static final int RIGHT_SEND_FILES = 8; + private static final int RIGHT_SEND_MUSIC = 9; + private static final int RIGHT_SEND_VOICE = 10; + private static final int RIGHT_SEND_ROUND = 11; + private static final int RIGHT_SEND_STICKERS = 12; + private static final int RIGHT_SEND_POLLS = 13; + private static final int RIGHT_SEND_LINKS = 14; + + private class Action { + int type; + String title; + + ArrayList options; + boolean[] checks; + boolean[] filter; + boolean collapsed; + int totalCount; + int filteredCount; + int selectedCount; + + Action(int type, ArrayList options) { + this.type = type; + totalCount = options.size(); + selectedCount = 0; + + if (totalCount > 0) { + this.options = options; + checks = new boolean[totalCount]; + collapsed = true; + + updateTitle(); + } + } + + int getCount() { + if (filter != null) { + return filteredCount; + } else { + return totalCount; + } + } + + boolean isPresent() { + return getCount() > 0; + } + + boolean isExpandable() { + return getCount() > 1; + } + + void setFilter(boolean[] filter) { + if (totalCount == 0) { + return; + } + this.filter = filter; + + updateCounters(); + updateTitle(); + } + + void updateCounters() { + selectedCount = 0; + filteredCount = 0; + for (int i = 0; i < totalCount; i++) { + if (filter == null) { + if (checks[i]) { + selectedCount++; + } + } else if (filter[i]) { + filteredCount++; + if (checks[i]) { + selectedCount++; + } + } + } + } + + TLObject first() { + for (int i = 0; i < totalCount; i++) { + if (filter == null || filter[i]) { + return options.get(i); + } + } + return null; + } + + void updateTitle() { + if (totalCount == 0) { + return; + } + + TLObject userOrChat = first(); + String name; + if (userOrChat instanceof TLRPC.User) { + name = UserObject.getUserName((TLRPC.User) userOrChat); + } else { + name = ContactsController.formatName(userOrChat); + } + if (type == ACTION_REPORT) { + title = getString(R.string.DeleteReportSpam); + } else if (type == ACTION_DELETE_ALL) { + title = isExpandable() ? getString(R.string.DeleteAllFromUsers) : formatString(R.string.DeleteAllFrom, name); + } else if (type == ACTION_BAN) { + if (restrict) { + title = isExpandable() ? getString(R.string.DeleteRestrictUsers) : formatString(R.string.DeleteRestrict, name); + } else { + title = isExpandable() ? getString(R.string.DeleteBanUsers) : formatString(R.string.DeleteBan, name); + } + } + } + + void collapseOrExpand() { + collapsed = !collapsed; + adapter.update(true); + } + + void toggleCheck(int index) { + if (filter != null && !filter[index]) { + return; + } + + this.checks[index] = !this.checks[index]; + if (this.checks[index]) { + selectedCount++; + } else { + selectedCount--; + } + adapter.update(true); + } + + void toggleAllChecks() { + boolean value = true; + for (int i = 0; i < totalCount; i++) { + if (checks[i] && (filter == null || filter[i])) { + value = false; + break; + } + } + Arrays.fill(checks, value); + updateCounters(); + adapter.update(true); + } + + void performAction(Utilities.IndexedConsumer action) { + for (int i = 0; i < totalCount; i++) { + if (checks[i] && (filter == null || filter[i])) { + action.accept(options.get(i), i); + } + } + } + + void forEach(Utilities.IndexedConsumer action) { + for (int i = 0; i < totalCount; i++) { + if (filter == null || filter[i]) { + action.accept(options.get(i), i); + } + } + } + } + + public DeleteMessagesBottomSheet(BaseFragment fragment, TLRPC.Chat inChat, ArrayList messages, ArrayList actionParticipants, TLRPC.ChannelParticipant[] channelParticipants, long mergeDialogId, int topicId, int mode, Runnable onDelete) { + super(fragment.getContext(), fragment, false, false, false, true, ActionBarType.SLIDING, fragment.getResourceProvider()); + setShowHandle(true); + fixNavigationBar(); + this.takeTranslationIntoAccount = true; + recyclerListView.setPadding(backgroundPaddingLeft, headerTotalHeight, backgroundPaddingLeft, dp(68)); + recyclerListView.setOnItemClickListener((view, position, x, y) -> { + UItem item = adapter.getItem(position - 1); + if (item == null) return; + onClick(item, view, position, x, y); + }); + this.takeTranslationIntoAccount = true; + DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { + @Override + protected void onMoveAnimationUpdate(RecyclerView.ViewHolder holder) { + super.onMoveAnimationUpdate(holder); + containerView.invalidate(); + } + }; + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDelayAnimations(false); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDurations(350); + recyclerListView.setItemAnimator(itemAnimator); + + buttonContainer = new SelectorBtnCell(getContext(), resourcesProvider, null); + buttonContainer.setClickable(true); + buttonContainer.setOrientation(LinearLayout.VERTICAL); + buttonContainer.setPadding(dp(10), dp(10), dp(10), dp(10)); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + + actionButton = new TextView(getContext()); + actionButton.setLines(1); + actionButton.setSingleLine(true); + actionButton.setGravity(Gravity.CENTER_HORIZONTAL); + actionButton.setEllipsize(TextUtils.TruncateAt.END); + actionButton.setGravity(Gravity.CENTER); + actionButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + actionButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + actionButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + actionButton.setText(getString(R.string.DeleteProceedBtn)); + actionButton.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_featuredStickers_addButton), 6)); + actionButton.setOnClickListener(e -> proceed()); + buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + this.inChat = inChat; + this.isForum = ChatObject.isForum(inChat); + this.messages = messages; + this.mergeDialogId = mergeDialogId; + this.topicId = topicId; + this.mode = mode; + this.onDelete = onDelete; + + this.defaultBannedRights = inChat.default_banned_rights; + this.bannedRights = new TLRPC.TL_chatBannedRights(); + if (defaultBannedRights.view_messages) { + bannedRights.view_messages = true; + } + if (defaultBannedRights.send_messages) { + bannedRights.send_messages = true; + } + if (defaultBannedRights.send_media) { + bannedRights.send_media = true; + } + if (defaultBannedRights.send_stickers) { + bannedRights.send_stickers = true; + } + if (defaultBannedRights.send_gifs) { + bannedRights.send_gifs = true; + } + if (defaultBannedRights.send_games) { + bannedRights.send_games = true; + } + if (defaultBannedRights.send_inline) { + bannedRights.send_inline = true; + } + if (defaultBannedRights.embed_links) { + bannedRights.embed_links = true; + } + if (defaultBannedRights.send_polls) { + bannedRights.send_polls = true; + } + if (defaultBannedRights.invite_users) { + bannedRights.invite_users = true; + } + if (defaultBannedRights.change_info) { + bannedRights.change_info = true; + } + if (defaultBannedRights.pin_messages) { + bannedRights.pin_messages = true; + } + if (defaultBannedRights.manage_topics) { + bannedRights.manage_topics = true; + } + if (defaultBannedRights.send_photos) { + bannedRights.send_photos = true; + } + if (defaultBannedRights.send_videos) { + bannedRights.send_videos = true; + } + if (defaultBannedRights.send_audios) { + bannedRights.send_audios = true; + } + if (defaultBannedRights.send_docs) { + bannedRights.send_docs = true; + } + if (defaultBannedRights.send_voices) { + bannedRights.send_voices = true; + } + if (defaultBannedRights.send_roundvideos) { + bannedRights.send_roundvideos = true; + } + if (defaultBannedRights.send_plain) { + bannedRights.send_plain = true; + } + + report = new Action(ACTION_REPORT, actionParticipants); + deleteAll = new Action(ACTION_DELETE_ALL, actionParticipants); + + if (ChatObject.canBlockUsers(inChat)) { + banFilter = new boolean[actionParticipants.size()]; + for (int i = 0; i < actionParticipants.size(); i++) { + TLRPC.ChannelParticipant channelParticipant = i < channelParticipants.length ? channelParticipants[i] : null; + if (!inChat.creator && (channelParticipant instanceof TLRPC.TL_channelParticipantAdmin || channelParticipant instanceof TLRPC.TL_channelParticipantCreator)) { + continue; + } + if (channelParticipant instanceof TLRPC.TL_channelParticipantBanned && channelParticipant.banned_rights != null && isBanned(channelParticipant.banned_rights)) { + continue; + } + + banFilter[i] = true; + } + + restrictFilter = new boolean[actionParticipants.size()]; + if (hasAnyDefaultRights()) { + for (int i = 0; i < actionParticipants.size(); i++) { + TLRPC.ChannelParticipant channelParticipant = i < channelParticipants.length ? channelParticipants[i] : null; + if (actionParticipants.get(i) instanceof TLRPC.Chat) { + continue; + } + if (channelParticipant instanceof TLRPC.TL_channelParticipantBanned && channelParticipant.banned_rights != null && !canBeRestricted(channelParticipant.banned_rights)) { + continue; + } + + if (banFilter[i]) { + restrictFilter[i] = true; + canRestrict = true; + } + } + } + + participantsBannedRights = Arrays.stream(channelParticipants) + .map(channelParticipant -> channelParticipant == null ? null : channelParticipant.banned_rights) + .collect(Collectors.toCollection(ArrayList::new)); + + banOrRestrict = new Action(ACTION_BAN, actionParticipants); + banOrRestrict.setFilter(banFilter); + } else { + banOrRestrict = new Action(ACTION_BAN, new ArrayList<>(0)); + } + + adapter.update(false); + actionBar.setTitle(getTitle()); + } + + private static boolean isBanned(TLRPC.TL_chatBannedRights bannedRights) { + return bannedRights.view_messages; + } + + private boolean hasAnyDefaultRights() { + return !defaultBannedRights.send_messages || + !defaultBannedRights.send_media || + !defaultBannedRights.send_stickers || + !defaultBannedRights.send_gifs || + !defaultBannedRights.send_games || + !defaultBannedRights.send_inline || + !defaultBannedRights.embed_links || + !defaultBannedRights.send_polls || + !defaultBannedRights.change_info || + !defaultBannedRights.invite_users || + !defaultBannedRights.pin_messages || + !defaultBannedRights.manage_topics && isForum || + !defaultBannedRights.send_photos || + !defaultBannedRights.send_videos || + !defaultBannedRights.send_roundvideos || + !defaultBannedRights.send_audios || + !defaultBannedRights.send_voices || + !defaultBannedRights.send_docs || + !defaultBannedRights.send_plain; + } + + public static TLRPC.TL_chatBannedRights bannedRightsOr(TLRPC.TL_chatBannedRights left, TLRPC.TL_chatBannedRights right) { + if (left == null) { + return right; + } + if (right == null) { + return left; + } + + TLRPC.TL_chatBannedRights bannedRights = new TLRPC.TL_chatBannedRights(); + bannedRights.view_messages = left.view_messages || right.view_messages; + bannedRights.send_messages = left.send_messages || right.send_messages; + bannedRights.send_media = left.send_media || right.send_media; + bannedRights.send_stickers = left.send_stickers || right.send_stickers; + bannedRights.send_gifs = left.send_gifs || right.send_gifs; + bannedRights.send_games = left.send_games || right.send_games; + bannedRights.send_inline = left.send_inline || right.send_inline; + bannedRights.embed_links = left.embed_links || right.embed_links; + bannedRights.send_polls = left.send_polls || right.send_polls; + bannedRights.change_info = left.change_info || right.change_info; + bannedRights.invite_users = left.invite_users || right.invite_users; + bannedRights.pin_messages = left.pin_messages || right.pin_messages; + bannedRights.manage_topics = left.manage_topics || right.manage_topics; + bannedRights.send_photos = left.send_photos || right.send_photos; + bannedRights.send_videos = left.send_videos || right.send_videos; + bannedRights.send_roundvideos = left.send_roundvideos || right.send_roundvideos; + bannedRights.send_audios = left.send_audios || right.send_audios; + bannedRights.send_voices = left.send_voices || right.send_voices; + bannedRights.send_docs = left.send_docs || right.send_docs; + bannedRights.send_plain = left.send_plain || right.send_plain; + return bannedRights; + } + + private boolean canBeRestricted(TLRPC.TL_chatBannedRights bannedRights) { + return !bannedRights.send_stickers && !defaultBannedRights.send_stickers || + !bannedRights.send_gifs && !defaultBannedRights.send_gifs || + !bannedRights.send_games && !defaultBannedRights.send_games || + !bannedRights.send_inline && !defaultBannedRights.send_inline || + !bannedRights.embed_links && !bannedRights.send_plain && !defaultBannedRights.embed_links && !defaultBannedRights.send_plain || + !bannedRights.send_polls && !defaultBannedRights.send_polls || + !bannedRights.change_info && !defaultBannedRights.change_info || + !bannedRights.invite_users && !defaultBannedRights.invite_users || + !bannedRights.pin_messages && !defaultBannedRights.pin_messages || + !bannedRights.manage_topics && !defaultBannedRights.manage_topics && isForum || + !bannedRights.send_photos && !defaultBannedRights.send_photos || + !bannedRights.send_videos && !defaultBannedRights.send_videos || + !bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos || + !bannedRights.send_audios && !defaultBannedRights.send_audios || + !bannedRights.send_voices && !defaultBannedRights.send_voices || + !bannedRights.send_docs && !defaultBannedRights.send_docs || + !bannedRights.send_plain && !defaultBannedRights.send_plain; + } + + @Override + protected CharSequence getTitle() { + return LocaleController.formatPluralString("DeleteOptionsTitle", messages != null ? messages.size() : 0); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + return adapter = new UniversalAdapter(listView, getContext(), currentAccount, getBaseFragment().getClassGuid(), true, this::fillItems, resourcesProvider); + } + + @Override + public void show() { + super.show(); + Bulletin.hideVisible(); + } + + private int getSendMediaSelectedCount() { + int i = 0; + if (!bannedRights.send_photos && !defaultBannedRights.send_photos) { + i++; + } + if (!bannedRights.send_videos && !defaultBannedRights.send_videos) { + i++; + } + if (!bannedRights.send_stickers && !defaultBannedRights.send_stickers) { + i++; + } + if (!bannedRights.send_audios && !defaultBannedRights.send_audios) { + i++; + } + if (!bannedRights.send_docs && !defaultBannedRights.send_docs) { + i++; + } + if (!bannedRights.send_voices && !defaultBannedRights.send_voices) { + i++; + } + if (!bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos) { + i++; + } + if (!bannedRights.embed_links && !defaultBannedRights.embed_links && !bannedRights.send_plain && !defaultBannedRights.send_plain) { + i++; + } + if (!bannedRights.send_polls && !defaultBannedRights.send_polls) { + i++; + } + return i; + } + + private boolean allDefaultMediaBanned() { + return defaultBannedRights.send_photos && defaultBannedRights.send_videos && defaultBannedRights.send_stickers + && defaultBannedRights.send_audios && defaultBannedRights.send_docs && defaultBannedRights.send_voices && + defaultBannedRights.send_roundvideos && defaultBannedRights.embed_links && defaultBannedRights.send_polls; + } + + private void fillAction(ArrayList items, Action action) { + if (!action.isPresent()) { + return; + } + + if (!action.isExpandable()) { + items.add(UItem.asRoundCheckbox(action.type, action.title) + .setChecked(action.selectedCount > 0)); + } else { + items.add(UItem.asUserGroupCheckbox(action.type, action.title, String.valueOf(action.selectedCount > 0 ? action.selectedCount : action.getCount())) + .setChecked(action.selectedCount > 0) + .setCollapsed(action.collapsed) + .setClickCallback((v) -> { + saveScrollPosition(); + action.collapseOrExpand(); + applyScrolledPosition(true); + })); + if (!action.collapsed) { + action.forEach((userOrChat, i) -> { + items.add(UItem.asUserCheckbox(action.type << 24 | i, userOrChat) + .setChecked(action.checks[i]) + .setPad(1)); + }); + } + } + } + + private void fillItems(ArrayList items, UniversalAdapter adapter) { + if (messages == null) { + return; + } + + items.add(UItem.asHeader(getString(R.string.DeleteAdditionalActions))); + fillAction(items, report); + fillAction(items, deleteAll); + fillAction(items, banOrRestrict); + + if (banOrRestrict.isPresent()) { + if (restrict) { + items.add(UItem.asShadow(null)); + if (banOrRestrict.isExpandable()) { + items.add(UItem.asAnimatedHeader(0, formatPluralString("UserRestrictionsCanDoUsers", banOrRestrict.selectedCount))); + } else { + items.add(UItem.asAnimatedHeader(0, getString(R.string.UserRestrictionsCanDo))); + } + + items.add(UItem.asSwitch(RIGHT_SEND_MESSAGES, getString(R.string.UserRestrictionsSend)) + .setChecked(!bannedRights.send_plain && !defaultBannedRights.send_plain) + .setLocked(defaultBannedRights.send_plain)); + + int sendMediaCount = getSendMediaSelectedCount(); + items.add(UItem.asExpandableSwitch(RIGHT_SEND_MEDIA, getString(R.string.UserRestrictionsSendMedia), String.format(Locale.US, "%d/9", sendMediaCount)) + .setChecked(sendMediaCount > 0) + .setLocked(allDefaultMediaBanned()) + .setCollapsed(sendMediaCollapsed) + .setClickCallback((v) -> { + if (allDefaultMediaBanned()) { + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) + .setMessage(LocaleController.getString(R.string.UserRestrictionsCantModifyDisabled)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .create() + .show(); + return; + } + boolean enabled = !(sendMediaCount > 0); + bannedRights.send_media = !enabled; + bannedRights.send_photos = !enabled; + bannedRights.send_videos = !enabled; + bannedRights.send_stickers = !enabled; + bannedRights.send_gifs = !enabled; + bannedRights.send_inline = !enabled; + bannedRights.send_games = !enabled; + bannedRights.send_audios = !enabled; + bannedRights.send_docs = !enabled; + bannedRights.send_voices = !enabled; + bannedRights.send_roundvideos = !enabled; + bannedRights.embed_links = !enabled; + bannedRights.send_polls = !enabled; + onRestrictionsChanged(); + + adapter.update(true); + })); + if (!sendMediaCollapsed) { + items.add(UItem.asRoundCheckbox(RIGHT_SEND_PHOTOS, getString(R.string.SendMediaPermissionPhotos)) + .setChecked(!bannedRights.send_photos && !defaultBannedRights.send_photos) + .setLocked(defaultBannedRights.send_photos) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_VIDEOS, getString(R.string.SendMediaPermissionVideos)) + .setChecked(!bannedRights.send_videos && !defaultBannedRights.send_videos) + .setLocked(defaultBannedRights.send_videos) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_FILES, getString(R.string.SendMediaPermissionFiles)) + .setChecked(!bannedRights.send_docs && !defaultBannedRights.send_docs) + .setLocked(defaultBannedRights.send_docs) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_MUSIC, getString(R.string.SendMediaPermissionMusic)) + .setChecked(!bannedRights.send_audios && !defaultBannedRights.send_audios) + .setLocked(defaultBannedRights.send_audios) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_VOICE, getString(R.string.SendMediaPermissionVoice)) + .setChecked(!bannedRights.send_voices && !defaultBannedRights.send_voices) + .setLocked(defaultBannedRights.send_voices) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_ROUND, getString(R.string.SendMediaPermissionRound)) + .setChecked(!bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos) + .setLocked(defaultBannedRights.send_roundvideos) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_STICKERS, getString(R.string.SendMediaPermissionStickersGifs)) + .setChecked(!bannedRights.send_stickers && !defaultBannedRights.send_stickers) + .setLocked(defaultBannedRights.send_stickers) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_POLLS, getString(R.string.SendMediaPolls)) + .setChecked(!bannedRights.send_polls && !defaultBannedRights.send_polls) + .setLocked(defaultBannedRights.send_polls) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_LINKS, getString(R.string.UserRestrictionsEmbedLinks)) + .setChecked(!bannedRights.embed_links && !defaultBannedRights.embed_links && !bannedRights.send_plain && !defaultBannedRights.send_plain) + .setLocked(defaultBannedRights.embed_links) + .setPad(1)); + } + + items.add(UItem.asSwitch(RIGHT_ADD_USERS, getString(R.string.UserRestrictionsInviteUsers)) + .setChecked(!bannedRights.invite_users && !defaultBannedRights.invite_users) + .setLocked(defaultBannedRights.invite_users)); + items.add(UItem.asSwitch(RIGHT_PIN_MESSAGES, getString(R.string.UserRestrictionsPinMessages)) + .setChecked(!bannedRights.pin_messages && !defaultBannedRights.pin_messages) + .setLocked(defaultBannedRights.pin_messages)); + items.add(UItem.asSwitch(RIGHT_CHANGE_CHAT_INFO, getString(R.string.UserRestrictionsChangeInfo)) + .setChecked(!bannedRights.change_info && !defaultBannedRights.change_info) + .setLocked(defaultBannedRights.change_info)); + if (isForum) { + items.add(UItem.asSwitch(RIGHT_CREATE_TOPICS, getString(R.string.CreateTopicsPermission)) + .setChecked(!bannedRights.manage_topics && !defaultBannedRights.manage_topics) + .setLocked(defaultBannedRights.manage_topics)); + } + } + + if (canRestrict) { + items.add(UItem.asShadowCollapseButton(1, getString(getRestrictToggleTextKey())) + .setCollapsed(!restrict) + .accent()); + } + } + } + + private int getRestrictToggleTextKey() { + if (!banOrRestrict.isExpandable()) { + if (restrict) { + return R.string.DeleteToggleBanUser; + } else { + return R.string.DeleteToggleRestrictUser; + } + } else { + if (restrict) { + return R.string.DeleteToggleBanUsers; + } else { + return R.string.DeleteToggleRestrictUsers; + } + } + } + + private void onRestrictionsChanged() { + if (restrict && banOrRestrict.isPresent() && banOrRestrict.selectedCount == 0) { + banOrRestrict.toggleAllChecks(); + } + } + + private float shiftDp = 10.0f; + private void onClick(UItem item, View view, int position, float x, float y) { + if (item.viewType == VIEW_TYPE_USER_CHECKBOX) { + int action = item.id >>> 24; + int index = item.id & 0xffffff; + + if (action == ACTION_REPORT) { + report.toggleCheck(index); + } else if (action == ACTION_DELETE_ALL) { + deleteAll.toggleCheck(index); + } else if (action == ACTION_BAN) { + banOrRestrict.toggleCheck(index); + } + } else if (item.viewType == VIEW_TYPE_USER_GROUP_CHECKBOX || item.viewType == VIEW_TYPE_ROUND_CHECKBOX) { + if (item.id == ACTION_REPORT) { + report.toggleAllChecks(); + } else if (item.id == ACTION_DELETE_ALL) { + deleteAll.toggleAllChecks(); + } else if (item.id == ACTION_BAN) { + banOrRestrict.toggleAllChecks(); + } else if (item.viewType == VIEW_TYPE_ROUND_CHECKBOX) { + if (item.locked) { + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) + .setMessage(LocaleController.getString(R.string.UserRestrictionsCantModifyDisabled)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .create() + .show(); + return; + } + + if (item.id == RIGHT_SEND_PHOTOS) { + bannedRights.send_photos = !bannedRights.send_photos; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_VIDEOS) { + bannedRights.send_videos = !bannedRights.send_videos; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_MUSIC) { + bannedRights.send_audios = !bannedRights.send_audios; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_FILES) { + bannedRights.send_docs = !bannedRights.send_docs; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_ROUND) { + bannedRights.send_roundvideos = !bannedRights.send_roundvideos; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_VOICE) { + bannedRights.send_voices = !bannedRights.send_voices; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_STICKERS) { + bannedRights.send_stickers = bannedRights.send_games = bannedRights.send_gifs = bannedRights.send_inline = !bannedRights.send_stickers; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_LINKS) { + if (bannedRights.send_plain || defaultBannedRights.send_plain) { + for (int i = 0; i < adapter.getItemCount(); i++) { + UItem childItem = adapter.getItem(i); + if (childItem.viewType == VIEW_TYPE_SWITCH && childItem.id == RIGHT_SEND_MESSAGES) { + RecyclerView.ViewHolder holder = recyclerListView.findViewHolderForAdapterPosition(i + 1); + if (holder != null) { + AndroidUtilities.shakeViewSpring(holder.itemView, shiftDp = -shiftDp); + } + break; + } + } + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + return; + } + bannedRights.embed_links = !bannedRights.embed_links; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_POLLS) { + bannedRights.send_polls = !bannedRights.send_polls; + onRestrictionsChanged(); + } + adapter.update(true); + } + } else if (item.viewType == VIEW_TYPE_SWITCH) { + if (item.locked) { + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) + .setMessage(LocaleController.getString(R.string.UserRestrictionsCantModifyDisabled)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .create() + .show(); + return; + } + + if (item.id == RIGHT_ADD_USERS) { + bannedRights.invite_users = !bannedRights.invite_users; + onRestrictionsChanged(); + } else if (item.id == RIGHT_PIN_MESSAGES) { + bannedRights.pin_messages = !bannedRights.pin_messages; + onRestrictionsChanged(); + } else if (item.id == RIGHT_CHANGE_CHAT_INFO) { + bannedRights.change_info = !bannedRights.change_info; + onRestrictionsChanged(); + } else if (item.id == RIGHT_CREATE_TOPICS) { + bannedRights.manage_topics = !bannedRights.manage_topics; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_MESSAGES) { + bannedRights.send_plain = !bannedRights.send_plain; + onRestrictionsChanged(); + } + + adapter.update(true); + } else if (item.viewType == VIEW_TYPE_EXPANDABLE_SWITCH) { + sendMediaCollapsed = !sendMediaCollapsed; + saveScrollPosition(); + adapter.update(true); + applyScrolledPosition(true); + } else if (item.viewType == VIEW_TYPE_SHADOW_COLLAPSE_BUTTON) { + restrict = !restrict; + banOrRestrict.setFilter(restrict ? restrictFilter : banFilter); + adapter.update(true); + } + } + + private void performDelete() { + ArrayList supergroupMessageIds = messages.stream() + .filter(msg -> msg.messageOwner.peer_id != null && msg.messageOwner.peer_id.chat_id != -mergeDialogId || mergeDialogId == 0) + .map(MessageObject::getId) + .collect(Collectors.toCollection(ArrayList::new)); + + ArrayList groupMessageIds = messages.stream() + .filter(msg -> msg.messageOwner.peer_id != null && msg.messageOwner.peer_id.chat_id == -mergeDialogId && mergeDialogId != 0) + .map(MessageObject::getId) + .collect(Collectors.toCollection(ArrayList::new)); + + if (!supergroupMessageIds.isEmpty()) { + MessagesController.getInstance(currentAccount).deleteMessages(supergroupMessageIds, null, null, -inChat.id, topicId, false, mode); + } + if (!groupMessageIds.isEmpty()) { + MessagesController.getInstance(currentAccount).deleteMessages(groupMessageIds, null, null, mergeDialogId, topicId, true, mode); + } + + banOrRestrict.performAction((participant, i) -> { + if (restrict) { + TLRPC.TL_chatBannedRights rights = bannedRightsOr(bannedRights, participantsBannedRights.get(i)); + if (participant instanceof TLRPC.User) { + MessagesController.getInstance(currentAccount).setParticipantBannedRole(inChat.id, (TLRPC.User) participant, null, rights, false, getBaseFragment()); + } else if (participant instanceof TLRPC.Chat) { + MessagesController.getInstance(currentAccount).setParticipantBannedRole(inChat.id, null, (TLRPC.Chat) participant, rights, false, getBaseFragment()); + } + } else { + if (participant instanceof TLRPC.User) { + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(inChat.id, (TLRPC.User) participant, null, false, false); + } else if (participant instanceof TLRPC.Chat) { + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(inChat.id, null, (TLRPC.Chat) participant, false, false); + } + } + }); + + report.performAction((participant, i) -> { + TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); + req.channel = MessagesController.getInputChannel(inChat); + if (participant instanceof TLRPC.User) { + req.participant = MessagesController.getInputPeer((TLRPC.User) participant); + } else if (participant instanceof TLRPC.Chat) { + req.participant = MessagesController.getInputPeer((TLRPC.Chat) participant); + } + req.id = messages.stream() + .filter(msg -> msg.messageOwner.peer_id != null && msg.messageOwner.peer_id.chat_id != -mergeDialogId) + .filter(msg -> { + if (participant instanceof TLRPC.User) { + return msg.messageOwner.from_id.user_id == ((TLRPC.User) participant).id; + } else if (participant instanceof TLRPC.Chat) { + return msg.messageOwner.from_id.user_id == ((TLRPC.Chat) participant).id; + } + return false; + }) + .map(MessageObject::getId) + .collect(Collectors.toCollection(ArrayList::new)); + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, null); + }); + + deleteAll.performAction((participant, i) -> { + if (participant instanceof TLRPC.User) { + MessagesController.getInstance(currentAccount).deleteUserChannelHistory(inChat, (TLRPC.User) participant, null, 0); + } else if (participant instanceof TLRPC.Chat) { + MessagesController.getInstance(currentAccount).deleteUserChannelHistory(inChat, null, (TLRPC.Chat) participant, 0); + } + }); + } + + private void proceed() { + dismiss(); + if (onDelete != null) { + onDelete.run(); + } + + String subtitle = ""; + if (report.selectedCount > 0) { + subtitle += formatPluralString("UsersReported", report.selectedCount); + } + if (banOrRestrict.selectedCount > 0) { + if (!TextUtils.isEmpty(subtitle)) { + subtitle += "\n"; + } + if (restrict) { + subtitle += formatPluralString("UsersRestricted", banOrRestrict.selectedCount); + } else { + subtitle += formatPluralString("UsersBanned", banOrRestrict.selectedCount); + } + } + + int icon = banOrRestrict.selectedCount > 0 ? R.raw.ic_admin : R.raw.contact_check; + if (TextUtils.isEmpty(subtitle)) { + BulletinFactory.of(getBaseFragment()).createSimpleBulletin(icon, getString(R.string.MessagesDeleted)).show(); + } else { + BulletinFactory.of(getBaseFragment()).createSimpleBulletin(icon, getString(R.string.MessagesDeleted), subtitle).show(); + } + + performDelete(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java new file mode 100644 index 000000000..a5d34b0f4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java @@ -0,0 +1,409 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.LocaleController.getString; + +import android.content.Context; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import org.checkerframework.checker.units.qual.A; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Adapters.DialogsSearchAdapter; +import org.telegram.ui.Cells.GraySectionCell; +import org.telegram.ui.Cells.ProfileSearchCell; +import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; +import org.telegram.ui.UserInfoActivity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +public class DialogsChannelsAdapter extends UniversalAdapter { + + private final Context context; + private final int currentAccount; + private final int folderId; + private final Theme.ResourcesProvider resourcesProvider; + + public final ArrayList messages = new ArrayList<>(); + public final ArrayList searchMyChannels = new ArrayList<>(); + public final ArrayList searchRecommendedChannels = new ArrayList<>(); + public final ArrayList searchChannels = new ArrayList<>(); + public boolean expandedSearchChannels; + + public boolean expandedMyChannels; + public final ArrayList myChannels = new ArrayList<>(); + + public DialogsChannelsAdapter(RecyclerListView listView, Context context, int currentAccount, int folderId, Theme.ResourcesProvider resourcesProvider) { + super(listView, context, currentAccount, 0, null, resourcesProvider); + super.fillItems = this::fillItems; + this.context = context; + this.currentAccount = currentAccount; + this.folderId = folderId; + this.resourcesProvider = resourcesProvider; + update(false); + } + + public void updateMyChannels() { + ArrayList channels = new ArrayList<>(); + ArrayList dialogs = MessagesController.getInstance(currentAccount).getAllDialogs(); + for (TLRPC.Dialog d : dialogs) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-d.id); + if (chat == null || !ChatObject.isChannelAndNotMegaGroup(chat) || !ChatObject.isPublic(chat) || ChatObject.isNotInChat(chat)) continue; + channels.add(chat); + if (channels.size() >= 100) + break; + } + myChannels.clear(); + myChannels.addAll(channels); + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + if (TextUtils.isEmpty(query)) { + if (myChannels != null && !myChannels.isEmpty()) { + if (myChannels.size() > 5) { + items.add(UItem.asGraySection(getString(R.string.SearchMyChannels), getString(expandedMyChannels ? R.string.ShowLess : R.string.ShowMore), this::toggleExpandedMyChannels)); + } else { + items.add(UItem.asGraySection(getString(R.string.SearchMyChannels))); + } + int count = myChannels.size(); + if (!expandedMyChannels) + count = Math.min(5, count); + for (int i = 0; i < count; ++i) { + items.add(UItem.asProfileCell(myChannels.get(i)).withUsername(true)); + } + } + MessagesController.ChannelRecommendations recommendations = MessagesController.getInstance(currentAccount).getCachedChannelRecommendations(0); + if (recommendations != null) { + ArrayList chats = new ArrayList<>(); + for (TLRPC.Chat chat : recommendations.chats) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + chats.add(chat); + } + if (!chats.isEmpty()) { + items.add(UItem.asGraySection(getString(R.string.SearchRecommendedChannels))); + } + for (TLRPC.Chat chat : chats) { + items.add(UItem.asProfileCell(chat)); + } + } else { + items.add(UItem.asFlicker(FlickerLoadingView.GRAY_SECTION)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + } + } else { + ArrayList foundChannels = new ArrayList<>(); + for (TLRPC.Chat chat : searchMyChannels) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + foundChannels.add(chat); + } + for (TLRPC.Chat chat : searchRecommendedChannels) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + foundChannels.add(chat); + } + for (TLRPC.Chat chat : searchChannels) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + foundChannels.add(chat); + } + if (!foundChannels.isEmpty()) { + if (foundChannels.size() > 5 && !messages.isEmpty()) { + items.add(UItem.asGraySection(getString(R.string.SearchChannels), getString(expandedSearchChannels ? R.string.ShowLess : R.string.ShowMore), this::toggleExpandedSearchChannels)); + } else { + items.add(UItem.asGraySection(getString(R.string.SearchChannels))); + } + int count = foundChannels.size(); + if (!expandedSearchChannels && !messages.isEmpty()) + count = Math.min(5, count); + for (int i = 0; i < count; ++i) { + items.add(UItem.asProfileCell(foundChannels.get(i))); + } + } + if (!messages.isEmpty()) { + items.add(UItem.asGraySection(getString(R.string.SearchMessages))); + for (MessageObject message : messages) { + items.add(UItem.asSearchMessage(message)); + } + if (hasMore) { + items.add(UItem.asFlicker(FlickerLoadingView.DIALOG_TYPE)); + } + } + } + } + + public void toggleExpandedSearchChannels(View view) { + expandedSearchChannels = !expandedSearchChannels; + update(true); + if (expandedSearchChannels) { + hideKeyboard(); + } + } + + public void toggleExpandedMyChannels(View view) { + expandedMyChannels = !expandedMyChannels; + update(true); + if (expandedMyChannels) { + hideKeyboard(); + } + } + + protected void hideKeyboard() { + + } + + public TLRPC.Chat getChat(int position) { + UItem item = getItem(position); + return item != null && item.object instanceof TLRPC.Chat ? (TLRPC.Chat) item.object : null; + } + + public Object getObject(int position) { + UItem item = getItem(position); + return item != null ? item.object : null; + } + + public boolean loadingMessages; + public boolean loadingChannels; + + private boolean hasMore; + private int allCount; + private int nextRate; + private int searchChannelsId; + public String query; + private void searchMessages(boolean next) { + loadingMessages = true; + final int searchId = ++searchChannelsId; + TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal(); + req.broadcasts_only = true; + if (folderId != 0) { + req.flags |= 1; + req.folder_id = folderId; + } + req.q = this.query; + req.limit = 25; + req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); + if (next && !messages.isEmpty()) { + MessageObject lastMessage = messages.get(messages.size() - 1); + req.offset_rate = nextRate; + req.offset_id = lastMessage.getId(); + if (lastMessage.messageOwner.peer_id == null) { + req.offset_peer = new TLRPC.TL_inputPeerEmpty(); + } else { + req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(lastMessage.messageOwner.peer_id); + } + } else { + req.offset_rate = 0; + req.offset_id = 0; + req.offset_peer = new TLRPC.TL_inputPeerEmpty(); + } + AndroidUtilities.runOnUIThread(() -> { + if (searchId != searchChannelsId || !TextUtils.equals(req.q, this.query)) return; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (searchId != searchChannelsId || !TextUtils.equals(req.q, this.query)) return; + loadingMessages = false; + if (!next) { + messages.clear(); + } + if (res instanceof TLRPC.messages_Messages) { + TLRPC.messages_Messages response = (TLRPC.messages_Messages) res; + MessagesStorage.getInstance(currentAccount).putUsersAndChats(response.users, response.chats, true, true); + MessagesController.getInstance(currentAccount).putUsers(response.users, false); + MessagesController.getInstance(currentAccount).putChats(response.chats, false); + + for (TLRPC.Message message : response.messages) { + MessageObject messageObject = new MessageObject(currentAccount, message, false, true); + messageObject.setQuery(query); + messages.add(messageObject); + } + + hasMore = response instanceof TLRPC.TL_messages_messagesSlice; + allCount = Math.max(messages.size(), response.count); + nextRate = response.next_rate; + } + update(true); + })); + }, next ? 800 : 0); + + if (!next) { + loadingChannels = true; + TLRPC.TL_contacts_search req2 = new TLRPC.TL_contacts_search(); + req2.limit = 20; + req2.q = this.query; + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (!TextUtils.equals(req2.q, this.query) || TextUtils.isEmpty(this.query)) return; + + loadingChannels = false; + TLRPC.TL_contacts_found response = null; + if (res instanceof TLRPC.TL_contacts_found) { + response = (TLRPC.TL_contacts_found) res; + MessagesStorage.getInstance(currentAccount).putUsersAndChats(response.users, response.chats, true, true); + MessagesController.getInstance(currentAccount).putUsers(response.users, false); + MessagesController.getInstance(currentAccount).putChats(response.chats, false); + } + + HashSet chatIds = new HashSet<>(); + + searchMyChannels.clear(); + if (response != null) { + for (TLRPC.Peer peer : response.my_results) { + if (!(peer instanceof TLRPC.TL_peerChannel)) continue; + TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(peer.channel_id); + if (channel == null) continue; + if (!ChatObject.isChannelAndNotMegaGroup(channel)) + continue; + if (chatIds.contains(channel.id)) + continue; + chatIds.add(channel.id); + searchMyChannels.add(channel); + } + } + + searchRecommendedChannels.clear(); + String q = this.query.toLowerCase(), qT = AndroidUtilities.translitSafe(q); + MessagesController.ChannelRecommendations recommendations = MessagesController.getInstance(currentAccount).getCachedChannelRecommendations(0); + if (recommendations != null && !recommendations.chats.isEmpty()) { + for (TLRPC.Chat chat : recommendations.chats) { + if (chat == null) + continue; + if (!ChatObject.isChannelAndNotMegaGroup(chat)) + continue; + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (!(ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat)))) + continue; + String t = chat.title.toLowerCase(), tT = AndroidUtilities.translitSafe(t); + if ( + t.startsWith(q) || t.contains(" " + q) || + tT.startsWith(qT) || tT.contains(" " + qT) + ) { + if (chatIds.contains(chat.id)) + continue; + chatIds.add(chat.id); + searchRecommendedChannels.add(chat); + } + } + } + + searchChannels.clear(); + if (response != null) { + for (TLRPC.Peer peer : response.results) { + if (!(peer instanceof TLRPC.TL_peerChannel)) continue; + TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(peer.channel_id); + if (channel == null) continue; + if (!ChatObject.isChannelAndNotMegaGroup(channel)) + continue; + if (chatIds.contains(channel.id)) + continue; + chatIds.add(channel.id); + searchChannels.add(channel); + } + } + + update(true); + })); + } + } + + private Runnable searchMessagesRunnable = () -> searchMessages(false); + public void search(String query) { + updateMyChannels(); + if (TextUtils.equals(query, this.query)) return; + this.query = query; + AndroidUtilities.cancelRunOnUIThread(searchMessagesRunnable); + if (TextUtils.isEmpty(this.query)) { + messages.clear(); + searchChannels.clear(); + searchRecommendedChannels.clear(); + searchMyChannels.clear(); + update(true); + searchChannelsId++; + loadingMessages = false; + loadingChannels = false; + hasMore = false; + nextRate = 0; + if (listView != null) { + listView.scrollToPosition(0); + } + return; + } + + messages.clear(); + searchChannels.clear(); + searchRecommendedChannels.clear(); + searchMyChannels.clear(); + + AndroidUtilities.runOnUIThread(searchMessagesRunnable, 1000); + loadingMessages = true; + loadingChannels = true; + + update(true); + + if (listView != null) { + listView.scrollToPosition(0); + } + } + + public void searchMore() { + if (!hasMore || loadingMessages || TextUtils.isEmpty(this.query)) { + return; + } + searchMessages(true); + } + + public ArrayList getNextChannels(int position) { + ArrayList channels = new ArrayList<>(); + for (int pos = position + 1; pos < getItemCount(); ++pos) { + TLRPC.Chat chat = getChat(pos); + if (chat == null) continue; + channels.add(chat); + } + return channels; + } + + public void checkBottom() { + if (!hasMore || loadingMessages || TextUtils.isEmpty(this.query) || listView == null) + return; + if (seesLoading()) { + searchMore(); + } + } + + public boolean seesLoading() { + if (listView == null) return false; + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + if (child instanceof FlickerLoadingView) { + return true; + } + } + return false; + } + + public boolean atTop() { + if (listView == null) return false; + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + if (listView.getChildAdapterPosition(child) == 0) + return true; + } + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index 1b80517e6..cdfc42d27 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -8,6 +8,9 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.getWallpaperRotation; + import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; @@ -15,8 +18,12 @@ import android.annotation.TargetApi; import android.content.Context; 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.PorterDuffXfermode; +import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.Rect; @@ -334,7 +341,7 @@ public class EditTextBoldCursor extends EditTextEffects { linePaint = new Paint(); activeLinePaint = new Paint(); errorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - errorPaint.setTextSize(AndroidUtilities.dp(11)); + errorPaint.setTextSize(dp(11)); if (Build.VERSION.SDK_INT >= 26) { setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO); } @@ -353,12 +360,12 @@ public class EditTextBoldCursor extends EditTextEffects { @Override public int getIntrinsicHeight() { - return AndroidUtilities.dp(cursorSize + 20); + return dp(cursorSize + 20); } @Override public int getIntrinsicWidth() { - return AndroidUtilities.dp(cursorWidth); + return dp(cursorWidth); } }; cursorDrawable.setShape(new RectShape()); @@ -418,7 +425,7 @@ public class EditTextBoldCursor extends EditTextEffects { } } - cursorSize = AndroidUtilities.dp(24); + cursorSize = dp(24); } @SuppressLint("PrivateApi") @@ -535,10 +542,10 @@ public class EditTextBoldCursor extends EditTextEffects { @Override public void setTextSize(int unit, float size) { if (hintAnimatedDrawable != null) { - hintAnimatedDrawable.setTextSize(AndroidUtilities.dp(size)); + hintAnimatedDrawable.setTextSize(dp(size)); } if (hintAnimatedDrawable2 != null) { - hintAnimatedDrawable2.setTextSize(AndroidUtilities.dp(size)); + hintAnimatedDrawable2.setTextSize(dp(size)); } super.setTextSize(unit, size); } @@ -605,12 +612,12 @@ public class EditTextBoldCursor extends EditTextEffects { setHintText(hint, false, hintLayout.getPaint()); } if (hintLayoutYFix) { - lineY = getExtendedPaddingTop() + getPaddingTop() + (getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() - AndroidUtilities.dp(1); + lineY = getExtendedPaddingTop() + getPaddingTop() + (getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() - dp(1); } else { - lineY = (getMeasuredHeight() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() + AndroidUtilities.dp(6); + lineY = (getMeasuredHeight() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() + dp(6); } } else { - lineY = getMeasuredHeight() - AndroidUtilities.dp(2); + lineY = getMeasuredHeight() - dp(2); } lastSize = currentSize; } @@ -650,7 +657,7 @@ public class EditTextBoldCursor extends EditTextEffects { return; } } - hintLayout = new StaticLayout(text, paint, AndroidUtilities.dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + hintLayout = new StaticLayout(text, paint, dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); invalidate(); } } @@ -791,7 +798,7 @@ public class EditTextBoldCursor extends EditTextEffects { hintAnimatedDrawable2.setAlpha((int) (Color.alpha(hintColor) * hintAlpha)); hintAnimatedDrawable2.draw(canvas); canvas.restore(); - hintAnimatedDrawable.setRightPadding(hintAnimatedDrawable2.getCurrentWidth() + AndroidUtilities.dp(2) - rightHintOffset); + hintAnimatedDrawable.setRightPadding(hintAnimatedDrawable2.getCurrentWidth() + dp(2) - rightHintOffset); } } else { hintAnimatedDrawable.setRightPadding(0); @@ -810,7 +817,7 @@ public class EditTextBoldCursor extends EditTextEffects { } if (supportRtlHint && LocaleController.isRTL) { float offset = getMeasuredWidth() - hintWidth; - canvas.translate(hintLayoutX = left + getScrollX() + offset, hintLayoutY = lineY - hintLayout.getHeight() - AndroidUtilities.dp(7)); + canvas.translate(hintLayoutX = left + getScrollX() + offset, hintLayoutY = lineY - hintLayout.getHeight() - dp(7)); } else { canvas.translate(hintLayoutX = left + getScrollX(), hintLayoutY = lineY - hintLayout.getHeight() - AndroidUtilities.dp2(7)); } @@ -823,7 +830,7 @@ public class EditTextBoldCursor extends EditTextEffects { canvas.translate(lineLeft * (1.0f - scale), 0); } canvas.scale(scale, scale); - canvas.translate(0, -AndroidUtilities.dp(22) * headerAnimationProgress); + canvas.translate(0, -dp(22) * headerAnimationProgress); getPaint().setColor(ColorUtils.blendARGB(hintColor, headerHintColor, headerAnimationProgress)); } else { getPaint().setColor(hintColor); @@ -850,6 +857,10 @@ public class EditTextBoldCursor extends EditTextEffects { protected void onDraw(Canvas canvas) { drawHint(canvas); + if (ellipsizeByGradient) { + canvas.saveLayerAlpha(getScrollX() + getPaddingLeft() - ellipsizeWidth, 0, getScrollX() + getWidth() - getPaddingRight() + ellipsizeWidth, getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + } + int topPadding = getExtendedPaddingTop(); scrollY = Integer.MAX_VALUE; try { @@ -916,7 +927,7 @@ public class EditTextBoldCursor extends EditTextEffects { updateCursorPosition(); Rect bounds = gradientDrawable.getBounds(); rect.left = bounds.left; - rect.right = bounds.left + AndroidUtilities.dp(cursorWidth); + rect.right = bounds.left + dp(cursorWidth); rect.bottom = bounds.bottom; rect.top = bounds.top; if (lineSpacingExtra != 0 && line < lineCount - 1) { @@ -954,7 +965,7 @@ public class EditTextBoldCursor extends EditTextEffects { updateCursorPosition(); Rect bounds = gradientDrawable.getBounds(); rect.left = bounds.left; - rect.right = bounds.left + AndroidUtilities.dp(cursorWidth); + rect.right = bounds.left + dp(cursorWidth); rect.bottom = bounds.bottom; rect.top = bounds.top; if (lineSpacingExtra != 0 && line < lineCount - 1) { @@ -974,11 +985,11 @@ public class EditTextBoldCursor extends EditTextEffects { } } if (lineVisible && lineColor != 0) { - int lineWidth = AndroidUtilities.dp(1); + int lineWidth = dp(1); boolean wasLineActive = lineActive; if (!TextUtils.isEmpty(errorText)) { linePaint.setColor(errorLineColor); - lineWidth = AndroidUtilities.dp(2); + lineWidth = dp(2); lineActive = false; } else if (isFocused()) { lineActive = true; @@ -999,7 +1010,7 @@ public class EditTextBoldCursor extends EditTextEffects { } int scrollHeight = (getLayout() == null ? 0 : getLayout().getHeight()) - getMeasuredHeight() + getPaddingBottom() + getPaddingTop(); - int bottom = (int) lineY + getScrollY() + Math.min(Math.max(0, scrollHeight - getScrollY()), AndroidUtilities.dp(2)); + int bottom = (int) lineY + getScrollY() + Math.min(Math.max(0, scrollHeight - getScrollY()), dp(2)); int centerX = lastTouchX < 0 ? getMeasuredWidth() / 2 : lastTouchX, maxWidth = Math.max(centerX, getMeasuredWidth() - centerX) * 2; if (lineActiveness < 1f) { @@ -1010,7 +1021,7 @@ public class EditTextBoldCursor extends EditTextEffects { if (lineActive) { activeLineWidth = maxWidth * lineActivenessT; } - int lineThickness = (int) ((lineActive ? 1 : lineActivenessT) * AndroidUtilities.dp(2)); + int lineThickness = (int) ((lineActive ? 1 : lineActivenessT) * dp(2)); canvas.drawRect( getScrollX() + Math.max(0, centerX - activeLineWidth / 2), bottom - lineThickness, @@ -1020,6 +1031,22 @@ public class EditTextBoldCursor extends EditTextEffects { ); } } + if (ellipsizeByGradient) { + canvas.save(); + canvas.translate(getScrollX(), 0); + ellipsizePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + ellipsizeMatrix.reset(); + ellipsizeGradient.setLocalMatrix(ellipsizeMatrix); + canvas.drawRect(getPaddingLeft() - ellipsizeWidth, 0, getPaddingLeft(), getHeight(), ellipsizePaint); + + ellipsizeMatrix.reset(); + ellipsizeMatrix.postScale(-1, 1, ellipsizeWidth / 2f, 0); + ellipsizeMatrix.postTranslate(getWidth() - getPaddingRight(), 0); + ellipsizeGradient.setLocalMatrix(ellipsizeMatrix); + canvas.drawRect(getWidth() - getPaddingRight(), 0, getWidth() - getPaddingRight() + ellipsizeWidth, getHeight(), ellipsizePaint); + canvas.restore(); + canvas.restore(); + } /*if (errorLayout != null) { canvas.save(); canvas.translate(getScrollX(), lineY + AndroidUtilities.dp(3)); @@ -1075,7 +1102,7 @@ public class EditTextBoldCursor extends EditTextEffects { private void updateCursorPosition(int top, int bottom, float horizontal) { final int left = clampHorizontalPosition(gradientDrawable, horizontal); - final int width = AndroidUtilities.dp(cursorWidth); + final int width = dp(cursorWidth); gradientDrawable.setBounds(left, top - mTempRect.top, left + width, bottom + mTempRect.bottom); } @@ -1236,4 +1263,24 @@ public class EditTextBoldCursor extends EditTextEffects { public Runnable getOnPremiumMenuLockClickListener() { return onPremiumMenuLockClickListener; } + + public boolean ellipsizeByGradient; + private Paint ellipsizePaint; + private LinearGradient ellipsizeGradient; + private Matrix ellipsizeMatrix; + private int ellipsizeWidth; + public void setEllipsizeByGradient(boolean value) { + if (ellipsizeByGradient = value) { + ellipsizeWidth = dp(12); + ellipsizePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + ellipsizeGradient = new LinearGradient(0, 0, ellipsizeWidth, 0, new int[] {0xFFFFFFFF, 0x00FFFFFF}, new float[] {0.4f, 1}, Shader.TileMode.CLAMP); + ellipsizePaint.setShader(ellipsizeGradient); + ellipsizeMatrix = new Matrix(); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java index db55fa969..619d5813a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java @@ -361,12 +361,16 @@ public class EditTextEffects extends EditText { } int newTextLength = (getLayout() == null || getLayout().getText() == null) ? 0 : getLayout().getText().length(); if (force || lastLayout != getLayout() || lastTextLength != newTextLength) { - animatedEmojiDrawables = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.getCacheTypeForEnterView(), this, animatedEmojiDrawables, getLayout()); + animatedEmojiDrawables = AnimatedEmojiSpan.update(emojiCacheType(), this, animatedEmojiDrawables, getLayout()); lastLayout = getLayout(); lastTextLength = newTextLength; } } + protected int emojiCacheType() { + return AnimatedEmojiDrawable.getCacheTypeForEnterView(); + } + private int lastText2Length; private int quoteUpdatesTries; private boolean[] quoteUpdateLayout; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java index d55d682d1..47af4bb15 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java @@ -639,7 +639,7 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N if (drawable == null) { continue; } - drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon))); + drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText))); // drawable.addView(this); ArrayList arrayList = viewsGroupedByLines.get(child.getTop()); if (arrayList == null) { @@ -773,7 +773,7 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N drawable.setAlpha(255); AndroidUtilities.rectTmp2.set(imageView.getLeft() + imageView.getPaddingLeft(), imageView.getPaddingTop(), imageView.getRight() - imageView.getPaddingRight(), imageView.getMeasuredHeight() - imageView.getPaddingBottom()); imageView.backgroundThreadDrawHolder[threadIndex].setBounds(AndroidUtilities.rectTmp2); - drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon))); + drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText))); imageView.imageReceiver = drawable.getImageReceiver();; drawInBackgroundViews.add(imageView); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index d6859ac47..ffe56f054 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -422,7 +422,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } - default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { + default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet, boolean edit) { } @@ -619,7 +619,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (set == null) { return; } - delegate.onShowStickerSet(null, set); + delegate.onShowStickerSet(null, set, false); } @Override @@ -648,6 +648,18 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } return emojiGridView.getAdapter() == emojiSearchAdapter ? emojiSearchAdapter.lastSearchEmojiString : null; } + + @Override + public void deleteSticker(TLRPC.Document document) { + TLRPC.TL_stickers_removeStickerFromSet req = new TLRPC.TL_stickers_removeStickerFromSet(); + req.sticker = MediaDataController.getInputStickerSetItem(document, "").document; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_messages_stickerSet) { + MediaDataController.getInstance(currentAccount).putStickerSet((TLRPC.TL_messages_stickerSet) response); + MediaDataController.getInstance(currentAccount).replaceStickerSet((TLRPC.TL_messages_stickerSet) response); + } + })); + } }; @Override @@ -860,7 +872,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific box.addView(clear, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); if (type != 1 || allowAnimatedEmoji && UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) { - categoriesListView = new StickerCategoriesListView(context, null, StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { + categoriesListView = new StickerCategoriesListView(context, null, type == 0 ? StickerCategoriesListView.CategoriesType.STICKERS : StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { @Override public void selectCategory(int categoryIndex) { super.selectCategory(categoryIndex); @@ -2176,7 +2188,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific query = stickersSearchGridAdapter.searchQuery; TLRPC.StickerSetCovered pack = stickersSearchGridAdapter.positionsToSets.get(position); if (pack != null) { - delegate.onShowStickerSet(pack.set, null); + delegate.onShowStickerSet(pack.set, null, false); return; } } @@ -4955,6 +4967,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } + public void scrollEmojiToTop() { + try { + emojiTabs.scrollTo(0, 0); + emojiTabs.onTabClick(0); + } catch (Exception ignore) {} + } + private void checkEmojiSearchFieldScroll(boolean isLayout) { if (delegate != null && delegate.isSearchOpened()) { RecyclerView.ViewHolder holder = emojiGridView.findViewHolderForAdapterPosition(0); @@ -6543,6 +6562,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } case 2: { StickerSetNameCell cell = (StickerSetNameCell) holder.itemView; + cell.setHeaderOnClick(null); if (position == groupStickerPackPosition) { int icon; if (groupStickersHidden && groupStickerSet == null) { @@ -6560,9 +6580,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific cell.setText(set.set.title, 0); if (set.set.creator && !StickersAlert.DISABLE_STICKER_EDITOR) { cell.setEdit(v -> { - delegate.onShowStickerSet(set.set, null); + delegate.onShowStickerSet(set.set, null, true); }); } + cell.setHeaderOnClick(v -> delegate.onShowStickerSet(set.set, null, false)); } } else if (object == recentStickers) { cell.setText(LocaleController.getString("RecentStickers", R.string.RecentStickers), R.drawable.msg_close, LocaleController.getString(R.string.ClearRecentStickersAlertTitle)); @@ -8606,6 +8627,48 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } + private void addPremiumStickers(Runnable finished) { + HashMap> allStickers = MediaDataController.getInstance(currentAccount).getAllStickers(); + + HashSet added = new HashSet<>(); + ArrayList stickers = new ArrayList<>(); + for (ArrayList documents : allStickers.values()) { + for (TLRPC.Document document : documents) { + if (!added.contains(document.id) && MessageObject.isPremiumSticker(document)) { + added.add(document.id); + stickers.add(document); + emojiStickersMap.put(document.id, document); + } + } + } + + ArrayList covers = MediaDataController.getInstance(currentAccount).getFeaturedStickerSets(); + for (TLRPC.StickerSetCovered set : covers) { + if (set.cover != null && !added.contains(set.cover.id) && MessageObject.isPremiumSticker(set.cover)) { + added.add(set.cover.id); + stickers.add(set.cover); + emojiStickersMap.put(set.cover.id, set.cover); + } + if (set.covers != null) { + for (TLRPC.Document document : set.covers) { + if (!added.contains(document.id) && MessageObject.isPremiumSticker(document)) { + added.add(document.id); + stickers.add(document); + emojiStickersMap.put(document.id, document); + } + } + } + } + + if (!stickers.isEmpty()) { + emojiStickersArray.addAll(stickers); + emojiStickers.put(emojiStickersArray, searchQuery); + emojiArrays.add(emojiStickersArray); + } + + finished.run(); + } + private void addLocalPacks(Runnable finished) { ArrayList local = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE); MessagesController.getInstance(currentAccount).filterPremiumStickers(local); @@ -8724,15 +8787,23 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stickersSearchField.showProgress(true); - Utilities.raceCallbacks( - this::searchFinish, + if ("premium".equalsIgnoreCase(query)) { + Utilities.raceCallbacks( + this::searchFinish, - this::addFromAllStickers, - this::addFromSuggestions, - this::addLocalPacks, - this::searchStickerSets, - this::searchStickers - ); + this::addPremiumStickers + ); + } else { + Utilities.raceCallbacks( + this::searchFinish, + + this::addFromAllStickers, + this::addFromSuggestions, + this::addLocalPacks, + this::searchStickerSets, + this::searchStickers + ); + } } }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java index ac5ff8975..70022ea7e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -48,6 +48,8 @@ public class FlickerLoadingView extends View { public static final int CHECKBOX_TYPE = 26; public final static int STORIES_TYPE = 27; public static final int SOTRY_VIEWS_USER_TYPE = 28; + public static final int PROFILE_SEARCH_CELL = 29; + public static final int GRAY_SECTION = 30; private int gradientWidth; private LinearGradient gradient; @@ -440,6 +442,41 @@ public class FlickerLoadingView extends View { break; } } + } else if (getViewType() == PROFILE_SEARCH_CELL) { + int k = 0; + while (h <= getMeasuredHeight()) { + int r = AndroidUtilities.dp(23); + canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(64) >> 1), r, paint); + + rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(17), paddingLeft + AndroidUtilities.dp(260), h + AndroidUtilities.dp(25)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(39), paddingLeft + AndroidUtilities.dp(140), h + AndroidUtilities.dp(47)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + h += getCellHeight(getMeasuredWidth()); + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } + } else if (getViewType() == GRAY_SECTION) { + int k = 0; + while (h <= getMeasuredHeight()) { + int cellHeight = getCellHeight(getMeasuredWidth()); + + rectF.set(0, h, getMeasuredWidth(), h + cellHeight); + checkRtl(rectF); + canvas.drawRect(rectF, paint); + + h += cellHeight; + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } } else if (getViewType() == CALL_LOG_TYPE) { int k = 0; while (h <= getMeasuredHeight()) { @@ -869,6 +906,10 @@ public class FlickerLoadingView extends View { return AndroidUtilities.dp(50) + 1; case SOTRY_VIEWS_USER_TYPE: return AndroidUtilities.dp(58); + case PROFILE_SEARCH_CELL: + return AndroidUtilities.dp(60) + 1; + case GRAY_SECTION: + return AndroidUtilities.dp(32); } return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java index 2bec00178..b7cdb3a6e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java @@ -201,11 +201,20 @@ public class ForumUtilities { } public static void openTopic(BaseFragment baseFragment, long chatId, TLRPC.TL_forumTopic topic, int fromMessageId) { + ChatActivity chatActivity = getChatActivityForTopic(baseFragment, chatId, topic, fromMessageId, new Bundle()); + if (chatActivity != null) { + baseFragment.presentFragment(chatActivity); + } + } + + public static ChatActivity getChatActivityForTopic(BaseFragment baseFragment, long chatId, TLRPC.TL_forumTopic topic, int fromMessageId, Bundle args) { if (baseFragment == null || topic == null) { - return; + return null; } TLRPC.Chat chatLocal = baseFragment.getMessagesController().getChat(chatId); - Bundle args = new Bundle(); + if (args == null) { + args = new Bundle(); + } args.putLong("chat_id", chatId); if (fromMessageId != 0) { @@ -226,7 +235,7 @@ public class ForumUtilities { } } if (message == null) { - return; + return null; } ArrayList messageObjects = new ArrayList<>(); messageObjects.add(new MessageObject(baseFragment.getCurrentAccount(), message, false, false)); @@ -234,7 +243,7 @@ public class ForumUtilities { if (fromMessageId != 0) { chatActivity.highlightMessageId = fromMessageId; } - baseFragment.presentFragment(chatActivity); + return chatActivity; } public static CharSequence getTopicSpannedName(TLRPC.ForumTopic topic, Paint paint, boolean isDialog) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java new file mode 100644 index 000000000..5a6ba17c2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java @@ -0,0 +1,153 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.StaticLayout; +import android.view.View; +import android.graphics.Rect; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.Theme; + +public class ForwardBackground { + + private final View view; + public final Path path = new Path(); + public final Rect bounds = new Rect(); + public final ButtonBounce bounce; + private final RectF r = new RectF(); + public float cx, cy; + + public ForwardBackground(View view) { + this.view = view; + bounce = new ButtonBounce(view, .8f, 1.4f); + } + + private int rippleDrawableColor; + private Drawable rippleDrawable; + + public void set(StaticLayout[] layout, boolean topLeftRad) { + final int h = dp(4) + (int) Theme.chat_forwardNamePaint.getTextSize() * 2; + + float pinnedR = Math.max(0, Math.min(6, SharedConfig.bubbleRadius) - 1); + float R = Math.min(9, SharedConfig.bubbleRadius); + float joinR = Math.min(3, SharedConfig.bubbleRadius); + + float pad = 4 + R / 9f * 2.66f; + float l = -dp(pad); + float t = -dp(3); + float b = h + dp(5); + + float w1 = layout[0].getLineWidth(0) + dp(pad); + float w2 = layout[1].getLineWidth(0) + dp(pad); + + float D; + + path.rewind(); + + D = 2 * dp(topLeftRad ? pinnedR : SharedConfig.bubbleRadius / 2f); + r.set(l, t, l + D, t + D); + path.arcTo(r, 180, 90); + + float w = w1; + if (Math.abs(w1 - w2) < dp(joinR + R)) { + w = Math.max(w1, w2); + } + + if (Math.abs(w1 - w2) > dp(joinR + R)) { + float d = 2 * dp(joinR); + float hm; + if (w1 < w2) { + hm = t + 0.45f * (b - t); + + D = 2 * dp(R); + r.set(w - D, t, w, t + D); + path.arcTo(r, 270, 90); + + r.set(w1, hm - d, w1 + d, hm); + path.arcTo(r, 180, -90); + + r.set(w2 - (b - hm), hm, w2, b); + path.arcTo(r, 270, 90); + + r.set(w2 - (b - hm), hm, w2, b); + path.arcTo(r, 0, 90); + } else { + hm = t + 0.55f * (b - t); + r.set(w - (hm - t), t, w, hm); + path.arcTo(r, 270, 90); + + D = 2 * dp(R); + r.set(w1 - (hm - t), t, w1, hm); + path.arcTo(r, 0, 90); + + r.set(w2, hm, w2 + d, hm + d); + path.arcTo(r, 270, -90); + + r.set(w2 - D, b - D, w2, b); + path.arcTo(r, 0, 90); + } + } else { + D = 2 * dp(R); + r.set(w - D, t, w, t + D); + path.arcTo(r, 270, 90); + + r.set(w - D, b - D, w, b); + path.arcTo(r, 0, 90); + } + + r.set(l, b - D, l + D, b); + path.arcTo(r, 90, 90); + + path.close(); + + bounds.set((int) l, (int) t, (int) Math.max(w1, w2), (int) b); + } + + public void setColor(int color) { + if (rippleDrawableColor != color) { + if (rippleDrawable == null) { + rippleDrawable = Theme.createSelectorDrawable(color, Theme.RIPPLE_MASK_ALL); + } else { + Theme.setSelectorDrawableColor(rippleDrawable, color, true); + } + rippleDrawableColor = color; + } + } + + public void setPressed(boolean pressed) { + setPressed(pressed, bounds.centerX(), bounds.centerY()); + } + + public void setPressed(boolean pressed, float x, float y) { + bounce.setPressed(pressed); + if (rippleDrawable != null) { + rippleDrawable.setState(pressed ? new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed} : new int[]{}); + } + if (pressed) { + cx = x; + cy = y; + if (rippleDrawable != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + rippleDrawable.setHotspot(x, y); + } + } + view.invalidate(); + } + + public void draw(Canvas canvas) { + canvas.save(); + canvas.clipPath(path); + if (rippleDrawable != null) { + rippleDrawable.setBounds(bounds); + rippleDrawable.draw(canvas); + } + canvas.restore(); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java index 149b3be0c..1e52c530f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -51,7 +51,6 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -176,7 +175,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private Size aspectRatio = SharedConfig.roundCamera16to9 ? new Size(16, 9) : new Size(4, 3); private TextureView textureView; private BackupImageView textureOverlayView; - private final boolean useCamera2 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.useCamera2; + private final boolean useCamera2 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.isUsingCamera2(currentAccount); private CameraSession cameraSession; private boolean bothCameras; private Camera2Session[] camera2Sessions = new Camera2Session[2]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java index 712d3b50d..0ae33b434 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java @@ -144,6 +144,13 @@ public class ItemOptions { return add(iconResId, text, Theme.key_actionBarDefaultSubmenuItemIcon, Theme.key_actionBarDefaultSubmenuItem, onClickListener); } + public ItemOptions addIf(boolean condition, int iconResId, Drawable iconDrawable, CharSequence text, Runnable onClickListener) { + if (!condition) { + return this; + } + return add(iconResId, iconDrawable, text, Theme.key_actionBarDefaultSubmenuItemIcon, Theme.key_actionBarDefaultSubmenuItem, onClickListener); + } + public ItemOptions add(CharSequence text, Runnable onClickListener) { return add(0, text, false, onClickListener); } @@ -161,14 +168,18 @@ public class ItemOptions { } public ItemOptions add(int iconResId, CharSequence text, int iconColorKey, int textColorKey, Runnable onClickListener) { + return add(iconResId, null, text, iconColorKey, textColorKey, onClickListener); + } + + public ItemOptions add(int iconResId, Drawable iconDrawable, CharSequence text, int iconColorKey, int textColorKey, Runnable onClickListener) { if (context == null) { return this; } ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider); subItem.setPadding(dp(18), 0, dp(18 + (LocaleController.isRTL ? 0 : 8)), 0); - if (iconResId != 0) { - subItem.setTextAndIcon(text, iconResId); + if (iconResId != 0 || iconDrawable != null) { + subItem.setTextAndIcon(text, iconResId, iconDrawable); } else { subItem.setText(text); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java index a474b0407..07ce097a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java @@ -3,11 +3,15 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; import android.content.Context; +import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.CornerPathEffect; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.os.SystemClock; import android.text.Layout; @@ -28,6 +32,7 @@ import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.LiteMode; +import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; @@ -661,6 +666,7 @@ public class LinkSpanDrawable { } canvas.restore(); } + super.onDraw(canvas); boolean restore = false; try { Layout layout = getLayout(); @@ -670,7 +676,11 @@ public class LinkSpanDrawable { restore = true; canvas.translate(getPaddingLeft(), offset); } - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, stack, 0, null, 0, 0, 0, 1f); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); + if (emojiColorFilter == null) { + emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); + } + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, stack, 0, null, 0, 0, 0, 1f, emojiColorFilter); } catch (Exception e) { if (!loggedError) FileLog.e(e, true); loggedError = true; @@ -678,25 +688,30 @@ public class LinkSpanDrawable { if (restore) { canvas.restore(); } - super.onDraw(canvas); } + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; + } + + private ColorFilter emojiColorFilter; + @Override public void setText(CharSequence text, TextView.BufferType type) { super.setText(text, type); - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, stack, getLayout()); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, stack, getLayout()); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, stack, getLayout()); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); } @Override @@ -704,6 +719,18 @@ public class LinkSpanDrawable { super.onDetachedFromWindow(); AnimatedEmojiSpan.release(this, stack); } + + @Override + public void setTextColor(int color) { + super.setTextColor(color); + emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); + } + + @Override + public void setTextColor(ColorStateList colors) { + super.setTextColor(colors); + emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); + } } public static class ClickableSmallTextView extends SimpleTextView { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java index 9f0d5095c..2614743bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -146,6 +146,11 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); getNotificationCenter().removeObserver(this, NotificationCenter.storiesEnabledUpdate); + if (applyBulletin != null) { + Runnable runnable = applyBulletin; + applyBulletin = null; + AndroidUtilities.runOnUIThread(runnable); + } } @Override @@ -437,7 +442,6 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } } sharedMediaLayout.closeActionMode(false); - sharedMediaLayout.disableScroll(false); if (pin) { sharedMediaLayout.scrollToPage(SharedMediaLayout.TAB_STORIES); } @@ -561,6 +565,10 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha return type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES; } + protected boolean customTabs() { + return type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES; + } + @Override protected boolean includeStories() { return type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java index 56b83596a..f8880acee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java @@ -26,7 +26,7 @@ public class OutlineTextContainerView extends FrameLayout { new SimpleFloatPropertyCompat("selectionProgress", obj -> obj.selectionProgress, (obj, value) -> { obj.selectionProgress = value; if (!obj.forceUseCenter) { - obj.outlinePaint.setStrokeWidth(obj.strokeWidthRegular + (obj.strokeWidthSelected - obj.strokeWidthRegular) * obj.selectionProgress); + obj.outlinePaint.setStrokeWidth(AndroidUtilities.lerp(obj.strokeWidthRegular, obj.strokeWidthSelected, obj.selectionProgress)); obj.updateColor(); } obj.invalidate(); @@ -50,7 +50,7 @@ public class OutlineTextContainerView extends FrameLayout { private float errorProgress; private float strokeWidthRegular = Math.max(2, AndroidUtilities.dp(0.5f)); - private float strokeWidthSelected = AndroidUtilities.dp(1.5f); + private float strokeWidthSelected = AndroidUtilities.dp(1.6667f); private EditText attachedEditText; private boolean forceUseCenter; @@ -157,7 +157,7 @@ public class OutlineTextContainerView extends FrameLayout { rect.set(getPaddingLeft() + AndroidUtilities.dp(PADDING_LEFT - PADDING_TEXT), getPaddingTop(), getWidth() - AndroidUtilities.dp(PADDING_LEFT + PADDING_TEXT) - getPaddingRight(), getPaddingTop() + stroke * 2); canvas.clipRect(rect, Region.Op.DIFFERENCE); rect.set(getPaddingLeft() + stroke, getPaddingTop() + stroke, getWidth() - stroke - getPaddingRight(), getHeight() - stroke - getPaddingBottom()); - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), outlinePaint); + canvas.drawRoundRect(rect, AndroidUtilities.dp(8), AndroidUtilities.dp(8), outlinePaint); canvas.restore(); float left = getPaddingLeft() + AndroidUtilities.dp(PADDING_LEFT - PADDING_TEXT), lineY = getPaddingTop() + stroke, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java index 901462234..0db67b311 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java @@ -74,7 +74,7 @@ public class Input { private ValueAnimator fillAnimator; private void fill(Brush brush, boolean registerUndo, Runnable onDone) { - if (!canFill || lastLocation == null) { + if (!canFill || renderView.getPainting().masking || lastLocation == null) { return; } @@ -245,11 +245,13 @@ public class Input { } points[pointsCount] = location; - if ((System.currentTimeMillis() - drawingStart) > 3000) { - detector.clear(); - renderView.getPainting().setHelperShape(null); - } else if (renderView.getCurrentBrush() instanceof Brush.Radial || renderView.getCurrentBrush() instanceof Brush.Elliptical) { - detector.append(location.x, location.y, distance > AndroidUtilities.dp(6) / scale); + if (renderView.getPainting() == null || !renderView.getPainting().masking) { + if ((System.currentTimeMillis() - drawingStart) > 3000) { + detector.clear(); + renderView.getPainting().setHelperShape(null); + } else if (renderView.getCurrentBrush() instanceof Brush.Radial || renderView.getCurrentBrush() instanceof Brush.Elliptical) { + detector.append(location.x, location.y, distance > AndroidUtilities.dp(6) / scale); + } } pointsCount++; realPointsCount++; @@ -337,9 +339,7 @@ public class Input { arrowAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (!renderView.getCurrentBrush().isEraser() || renderView.getUndoStore().canUndo()) { - renderView.getPainting().commitPath(null, renderView.getCurrentColor()); - } + renderView.getPainting().commitPath(null, renderView.getCurrentColor()); arrowAnimator = null; } }); @@ -349,7 +349,7 @@ public class Input { } } - if (commit && (!renderView.getCurrentBrush().isEraser() || renderView.getUndoStore().canUndo())) { + if (commit) { renderView.getPainting().commitPath(null, renderView.getCurrentColor(), true, () -> { if (switchedBrushByStylusFrom != null) { renderView.selectBrush(switchedBrushByStylusFrom); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java new file mode 100644 index 000000000..04d9d46e5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java @@ -0,0 +1,459 @@ +package org.telegram.ui.Components.Paint; +public class ObjectDetectionEmojis { + private static String[] labelEmojis; + public static String labelToEmoji(int labelId) { + if (labelEmojis == null) { + labelEmojis = new String[] { + "👥", // Team + "🔥", // Bonfire + "📚", // Comics + "🏔", // Himalayan + "🧊", // Iceberg + "🍱", // Bento + null, + "🚰", // Sink + "🧸", // Toy + "🗿", // Statue + "🍔", // Cheeseburger + "🚜", // Tractor + "🛷", // Sled + "🐠", // Aquarium + "🎪", // Circus + null, + "🪑", // Sitting + "🧔", // Beard + "🌉", // Bridge + "🩰", // Tights + "🐦", // Bird + "🚣", // Rafting + "🏞", // Park + null, + "🏭", // Factory + "🎓", // Graduation + "🍶", // Porcelain + "🌿", // Twig + "🌸", // Petal + "🛋", // Cushion + "😎", // Sunglasses + "🏗", // Infrastructure + "🎡", // Ferris wheel + "🐠", // Pomacentridae + "🤿", // Wetsuit + "🐶", // Shetland Sheepdog + "⛵", // Brig + "🎨", // Watercolor Paint + "🏆", // Competition + "🧗", // Cliff + "🏸", // Badminton + "🦁", // Safari + "🚲", // Bicycle + "🏟", // Stadium + null, + "⛵", // Boat + "🙂", // Smile + "🏄", // Surfboard + "🍟", // Fast Food + "🌇", // Sunset + "🌭", // Hot Dog + "🩳", // Shorts + "🚌", // Bus + "🐂", // Bullfighting + "🌌", // Sky + "🐹", // Gerbil + "🪨", // Rock + "👥", // Interaction + "👗", // Dress + "👣", // Toe + null, + "🐻", // Bear + "🍽", // Eating + "🗼", // Tower + "🧱", // Brick + "🗑", // Junk + "👤", // Person + "🏄", // Windsurfing + "👙", // Swimwear + "🎢", // Roller + "🏕", // Camping + "🎠", // Playground + "🚽", // Bathroom + "😆", // Laugh + "🎈", // Balloon + "🎤", // Concert + "👗", // Prom + "🚧", // Construction + "📦", // Product + "🐠", // Reef + "🧺", // Picnic + "🌼", // Wreath + "🛒", // Wheelbarrow + "🥊", // Boxer + "💍", // Necklace + "💎", // Bracelet + "🎰", // Casino + "🚗", // Windshield + "🪜", // Stairs + "💻", // Computer + "🍳", // Cookware and Bakeware + "📽️", // Monochrome + "🪑", // Chair + "🖼", // Poster + "🍷", // Bar + "🚢", // Shipwreck + "🛳", // Pier + "👥", // Community + "🧗", // Caving + "🕳", // Cave + "👔", // Tie + "🛠", // Cabinetry + "🌊", // Underwater + "🤡", // Clown + "🎉", // Nightclub + "🚴", // Cycling + "☄️", // Comet + "🎓", // Mortarboard + "🏟", // Track + "🎄", // Christmas + "⛪", // Church + "🕰", // Clock + "👨", // Dude + "🐄", // Cattle + "🌴", // Jungle + "🖥", // Desk + "🥌", // Curling + "🍲", // Cuisine + "🐱", // Cat + "🧃", // Juice + "🍚", // Couscous + null, // "📸", // Screenshot + "👥", // Crew + "🏙", // Skyline + null, + "🧸", // Stuffed Toy + "🍪", // Cookie + "🟩", // Tile + "🕎", // Hanukkah + "🧶", // Crochet + "🛹", // Skateboarder + "✂️", // Clipper + "💅", // Nail + "🥤", // Cola + "🍴", // Cutlery + "📜", // Menu + null, + "👘", // Sari + "🧸", // Plush + "📱", // Pocket + "🚦", // Neon + "❄️", // Icicle + "🇵🇷", // Pasteles + "⛓", // Chain + "💃", // Dance + "🏜", // Dune + "🎅", // Santa Claus + "🦃", // Thanksgiving + "🤵", // Tuxedo + "👄", // Mouth + "🏜", // Desert + "🦕", // Dinosaur + "👳‍♂️", // Mufti + "🔥", // Fire + "🛏", // Bedroom + "🥽", // Goggles + "🐉", // Dragon + "🛋", // Couch + "🛷", // Sledding + "🧢", // Cap + "📋", // Whiteboard + "🎩", // Hat + "🍨", // Gelato + "🐎", // Cavalier + "🧶", // Beanie + "👕", // Jersey + "🧣", // Scarf + "🏖", // Vacation + "⚽", // Pitch + "🖤", // Blackboard + "🎧", // Deejay + "🏛", // Monument + "🚘", // Bumper + "🛹", // Longboard + "🦢", // Waterfowl + "🍖", // Flesh + "🥅", // Net + "🧁", // Icing + "🐕", // Dalmatian + "🚤", // Speedboat + "🌳", // Trunk + "☕", // Coffee + "⚽", // Soccer + "🧸", // Ragdoll + "🍲", // Food + "🧍", // Standing + "📖", // Fiction + "🍉", // Fruit + "🍜", // Pho + "✨", // Sparkler + "💼", // Presentation + "🌳", // Swing + "🐕", // Cairn Terrier + "🌲", // Forest + "🚩", // Flag + "⛵", // Frigate + "🦶", // Foot + "🧥", // Jacket + null, + "🛏", // Pillow + null, + "🛁", // Bathing + "🗻", // Glacier + "🤸‍♀️", // Gymnastics + "👂", // Ear + "🌸", // Flora + "🐚", // Shell + "👵", // Grandparent + "🏛", // Ruins + "👁️", // Eyelash + "🛏", // Bunk Bed + "⚖️", // Balance + "🎒", // Backpacking + "🐎", // Horse + "✨", // Glitter + "🛸", // Saucer + "💇", // Hair + "🧸", // Miniature + "👥", // Crowd + "🪟", // Curtain + "🌟", // Icon + "🐱", // Pixie-bob + "🐄", // Herd + "🐞", // Insect + "❄️", // Ice + "💍", // Bangle + "🚪", // Flap + "💎", // Jewellery + "🧶", // Knitting + "🏺", // Centrepiece + "🧥", // Outerwear + "❤️", // Love + "💪", // Muscle + "🏍", // Motorcycle + "💰", // Money + "🕌", // Mosque + "🍽", // Tableware + "💃", // Ballroom + "🛶", // Kayak + "🏖", // Leisure + "🧾", // Receipt + "🏞", // Lake + "🚨", // Lighthouse + "🐴", // Bridle + "🧥", // Leather + "📯", // Horn + "⌚", // Strap + "🧱", // Lego + "🤿", // Scuba Diving + "👖", // Leggings + "🏊", // Pool + "🎸", // Musical Instrument + "🎭", // Musical + "🤘", // Metal + "🌕", // Moon + "🧥", // Blazer + "💍", // Marriage + "📱", // Mobile Phone + "🪖", // Militia + "🍽", // Tablecloth + "🎉", // Party + "🌌", // Nebula + "📰", // News + "🗞", // Newspaper + null, + "🎹", // Piano + "🪴", // Plant + "🛂", // Passport + "🐧", // Penguin + "🐕", // Shikoku + "🏰", // Palace + "🏵", // Doily + "🏇", // Polo + "📝", // Paper + "🎶", // Pop Music + "⛵", // Skiff + "🍕", // Pizza + "🐾", // Pet + "🧵", // Quilting + "🐦", // Cage + "🛹", // Skateboard + "🏄", // Surfing + "🏉", // Rugby + "💄", // Lipstick + "🏞", // River + "🏁", // Race + "🚣", // Rowing + "🛣", // Road + "🏃", // Running + "🛋", // Room + "🏠", // Roof + "⭐", // Star + "🏅", // Sports + "👟", // Shoe + "🚤", // Tubing + "🪐", // Space + "😴", // Sleep + "🤲", // Skin + "🏊", // Swimming + "🏫", // School + "🍣", // Sushi + "🛋", // Loveseat + "🦸", // Superman + "😎", // Cool + "⛷", // Skiing + "🚢", // Submarine + "🎵", // Song + "📚", // Class + "🏙", // Skyscraper + "🌋", // Volcano + "📺", // Television + "🐎", // Rein + "💉", // Tattoo + "🚆", // Train + "🚪", // Handrail + "🥤", // Cup + "🚗", // Vehicle + "👜", // Handbag + "💡", // Lampshade + "🎫", // Event + "🍷", // Wine + "🍗", // Wing + "🎡", // Wheel + "🏄", // Wakeboarding + "💻", // Web Page + null, + null, + "🏡", // Ranch + "🎣", // Fishing + "❤️", // Heart + "🌱", // Cotton + "☕", // Cappuccino + "🍞", // Bread + "🏖", // Sand + null, + "🏛", // Museum + "🚁", // Helicopter + "⛰", // Mountain + "🦆", // Duck + "🌱", // Soil + "🐢", // Turtle + "🐊", // Crocodile + "🎶", // Musician + "👟", // Sneakers + "🧶", // Wool + "💍", // Ring + "🎤", // Singer + "🎡", // Carnival + "🏂", // Snowboarding + "🚤", // Waterskiing + "🧱", // Wall + "🚀", // Rocket + "🏠", // Countertop + "🏖", // Beach + "🌈", // Rainbow + "🌿", // Branch + "👨", // Moustache + "🌷", // Garden + "👗", // Gown + "🏞", // Field + "🐶", // Dog + "🦸", // Superhero + "🌸", // Flower + "🍽", // Placemat + "🔊", // Subwoofer + "⛪", // Cathedral + "🏢", // Building + "✈️", // Airplane + "🐾", // Fur + "🐂", // Bull + "🪑", // Bench + "🛕", // Temple + "🦋", // Butterfly + "👠", // Model + "🏃", // Marathon + "🪡", // Needlework + "🍳", // Kitchen + "🏰", // Castle + "🌌", // Aurora + "🐛", // Larva + "🏎", // Racing + null, + "✈️", // Airliner + "🚣", // Dam + "🧵", // Textile + "🤵", // Groom + "🎢", // Fun + "🍲", // Steaming + "🥦", // Vegetable + "🚲", // Unicycle + "👖", // Jeans + "🪴", // Flowerpot + "🗄", // Drawer + "🎂", // Cake + "💺", // Armrest + "✈️", // Aviation + null, + "🌫", // Fog + "🎆", // Fireworks + "🚜", // Farm + "🦭", // Seal + "📚", // Shelf + "💇", // Bangs + "⚡", // Lightning + "🚐", // Van + "🐱", // Sphynx + "🚗", // Tire + "👖", // Denim + "🌾", // Prairie + "🤿", // Snorkeling + "☔", // Umbrella + "🛣", // Asphalt + "⛵", // Sailboat + "🐶", // Basset Hound + "🔳", // Pattern + "🍽", // Supper + "👰", // Veil + "💧", // Waterfall + null, + "🍴", // Lunch + "🚙", // Odometer + "👶", // Baby + "👓", // Glasses + "🚗", // Car + "✈️", // Aircraft + "✋", // Hand + "🐎", // Rodeo + "🏞", // Canyon + "🍽", // Meal + "⚾", // Softball + "🍷", // Alcohol + "👰", // Bride + "🌿", // Swamp + "🥧", // Pie + "🎒", // Bag + "🃏", // Joker + "🦹", // Supervillain + "🪖", // Army + "🛶", // Canoe + "🤳", // Selfie + "🛺", // Rickshaw + "🏚", // Barn + "🏹", // Archery + "🚀", // Aerospace Engineering + null, + "⛈", // Storm + "⛑", // Helmet + }; + } + if (labelId < 0 || labelId >= labelEmojis.length) return null; + return labelEmojis[labelId]; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java index 666c3b103..0747177f2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java @@ -59,6 +59,7 @@ public class Painting { private Brush brush; private HashMap brushTextures = new HashMap<>(); private Texture bitmapTexture; + private Texture originalBitmapTexture; private ByteBuffer vertexBuffer; private ByteBuffer textureBuffer; private int reusableFramebuffer; @@ -126,6 +127,13 @@ public class Painting { } } + public boolean masking = false; + + public Painting asMask() { + this.masking = true; + return this; + } + public void setDelegate(PaintingDelegate paintingDelegate) { delegate = paintingDelegate; } @@ -167,6 +175,9 @@ public class Painting { if (bitmapBlurTexture == null) { bitmapBlurTexture = new Texture(blurBitmap); } + if (masking && originalBitmapTexture == null) { + originalBitmapTexture = new Texture(imageBitmap); + } } private boolean helperShown; @@ -855,7 +866,8 @@ public class Painting { brush = this.brush; } - Shader shader = shaders.get(brush.getShaderName(Brush.PAINT_TYPE_BLIT)); + final boolean masking = this.masking && (brush instanceof Brush.Radial || brush instanceof Brush.Eraser); + Shader shader = shaders.get(brush.getShaderName(Brush.PAINT_TYPE_BLIT) + (masking ? "_masking" : "")); if (shader == null) { return; } @@ -875,6 +887,14 @@ public class Painting { GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mask); + if (masking) { + GLES20.glUniform1i(shader.getUniform("otexture"), 2); + GLES20.glUniform1f(shader.getUniform("preview"), 0.4f); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE2); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, originalBitmapTexture.texture()); + } + Object lock = null; if (brush instanceof Brush.Blurer) { GLES20.glUniform1i(shader.getUniform("blured"), 2); @@ -886,7 +906,7 @@ public class Painting { GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, bluredTexture.texture()); } } - + GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); GLES20.glVertexAttribPointer(0, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer); @@ -906,7 +926,7 @@ public class Painting { } private void renderBlit(int texture, float alpha) { - Shader shader = shaders.get("blit"); + Shader shader = shaders.get(masking ? "maskingBlit" : "blit"); if (texture == 0 || shader == null) { return; } @@ -914,11 +934,24 @@ public class Painting { GLES20.glUseProgram(shader.program); GLES20.glUniformMatrix4fv(shader.getUniform("mvpMatrix"), 1, false, FloatBuffer.wrap(renderProjection)); - GLES20.glUniform1i(shader.getUniform("texture"), 0); GLES20.glUniform1f(shader.getUniform("alpha"), alpha); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); + if (masking) { + GLES20.glUniform1i(shader.getUniform("texture"), 1); + GLES20.glUniform1i(shader.getUniform("mask"), 0); + GLES20.glUniform1f(shader.getUniform("preview"), 0.4f); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, originalBitmapTexture.texture()); + } else { + GLES20.glUniform1i(shader.getUniform("texture"), 0); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); + } GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); @@ -963,7 +996,7 @@ public class Painting { if (shaders == null) { return null; } - Shader shader = shaders.get(undo ? "nonPremultipliedBlit" : "blit"); + Shader shader = shaders.get(undo ? "nonPremultipliedBlit" : (masking ? "maskingBlit" : "blit")); if (shader == null) { return null; } @@ -976,10 +1009,22 @@ public class Painting { GLES20.glUniformMatrix4fv(shader.getUniform("mvpMatrix"), 1, false, FloatBuffer.wrap(finalProjection)); - GLES20.glUniform1i(shader.getUniform("texture"), 0); + if (!undo && masking) { + GLES20.glUniform1i(shader.getUniform("texture"), 1); + GLES20.glUniform1i(shader.getUniform("mask"), 0); + GLES20.glUniform1f(shader.getUniform("preview"), 0); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, onlyBlur && bitmapBlurTexture != null ? bitmapBlurTexture.texture() : getTexture()); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, onlyBlur && bitmapBlurTexture != null ? bitmapBlurTexture.texture() : getTexture()); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, originalBitmapTexture.texture()); + } else { + GLES20.glUniform1i(shader.getUniform("texture"), 0); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, onlyBlur && bitmapBlurTexture != null ? bitmapBlurTexture.texture() : getTexture()); + } GLES20.glClearColor(0, 0, 0, 0); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); @@ -1160,6 +1205,9 @@ public class Painting { if (bluredTexture != null) { bluredTexture.cleanResources(true); } + if (originalBitmapTexture != null) { + originalBitmapTexture.cleanResources(true); + } if (shaders != null) { for (Shader shader : shaders.values()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java index 1a1900436..e2de81b3e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java @@ -55,24 +55,47 @@ public class ShaderSet { "precision highp float;" + "varying vec2 varTexcoord;" + "uniform sampler2D texture;" + -// "uniform float alpha;" + "void main (void) {" + " gl_FragColor = texture2D(texture, varTexcoord.st, 0.0);" + -// " gl_FragColor.a *= alpha;" + + " gl_FragColor.rgb *= gl_FragColor.a;" + + "}"; + private static final String PAINT_MASKING_BLIT_FSH = + "precision highp float;" + + "varying vec2 varTexcoord;" + + "uniform sampler2D texture;" + + "uniform sampler2D mask;" + + "uniform float preview;" + + "void main (void) {" + + " gl_FragColor = texture2D(texture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * texture2D(mask, varTexcoord.st, 0.0).a);" + " gl_FragColor.rgb *= gl_FragColor.a;" + "}"; private static final String PAINT_BLITWITHMASK_FSH = "precision highp float;" + "varying vec2 varTexcoord;" + "uniform sampler2D texture;" + + "uniform sampler2D otexture;" + "uniform sampler2D mask;" + "uniform vec4 color;" + "void main (void) {" + " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + " float outAlpha = srcAlpha + dst.a * (1.0 - srcAlpha);" + - " gl_FragColor.rgb = (color.rgb * srcAlpha + dst.rgb * dst.a * (1.0 - srcAlpha)) / outAlpha;" + + " gl_FragColor.rgb = (color.rgb * srcAlpha + dst.rgb * dst.a * (1.0 - srcAlpha));" + " gl_FragColor.a = outAlpha;" + + "}"; + private static final String PAINT_MASKING_BLITWITHMASK_FSH = + "precision highp float;" + + "varying vec2 varTexcoord;" + + "uniform sampler2D texture;" + + "uniform sampler2D otexture;" + + "uniform sampler2D mask;" + + "uniform vec4 color;" + + "uniform float preview;" + + "void main (void) {" + + " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + + " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + + " float outAlpha = srcAlpha + dst.a * (1.0 - srcAlpha);" + + " gl_FragColor = texture2D(otexture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * outAlpha);" + " gl_FragColor.rgb *= gl_FragColor.a;" + "}"; private static final String PAINT_COMPOSITEWITHMASK_FSH = @@ -161,6 +184,37 @@ public class ShaderSet { " gl_FragColor.a = outAlpha;" + " gl_FragColor.rgb *= gl_FragColor.a;" + "}"; + private static final String PAINT_MASKING_BLITWITHMASKERASER_FSH = + "precision highp float;" + + "varying vec2 varTexcoord;" + + "uniform sampler2D texture;" + + "uniform sampler2D otexture;" + + "uniform sampler2D mask;" + + "uniform vec4 color;" + + "uniform float preview;" + + "void main (void) {" + + " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + + " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + + " float outAlpha = dst.a * (1. - srcAlpha);" + + " gl_FragColor = texture2D(otexture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * outAlpha);" + + " gl_FragColor.rgb *= gl_FragColor.a;" + + "}"; +// +// +// "precision highp float;" + +// "varying vec2 varTexcoord;" + +// "uniform sampler2D texture;" + +// "uniform sampler2D otexture;" + +// "uniform sampler2D mask;" + +// "uniform vec4 color;" + +// "uniform float preview;" + +// "void main (void) {" + +// " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + +// " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + +// " float outAlpha = srcAlpha + dst.a * (1.0 - srcAlpha);" + +// " gl_FragColor = texture2D(otexture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * outAlpha);" + +// " gl_FragColor.rgb *= gl_FragColor.a;" + +// "}"; private static final String PAINT_COMPOSITEWITHMASKERASER_FSH = "precision highp float;" + "varying vec2 varTexcoord;" + @@ -344,6 +398,13 @@ public class ShaderSet { shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "alpha"}); result.put("blit", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); + shader.put(VERTEX, PAINT_BLIT_VSH); + shader.put(FRAGMENT, PAINT_MASKING_BLIT_FSH); + shader.put(ATTRIBUTES, new String[]{"inPosition", "inTexcoord"}); + shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "mask", "alpha", "preview"}); + result.put("maskingBlit", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); shader.put(VERTEX, PAINT_BLIT_VSH); shader.put(FRAGMENT, PAINT_BLITWITHMASK_FSH); @@ -351,6 +412,13 @@ public class ShaderSet { shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "mask", "color"}); result.put("blitWithMask", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); + shader.put(VERTEX, PAINT_BLIT_VSH); + shader.put(FRAGMENT, PAINT_MASKING_BLITWITHMASK_FSH); + shader.put(ATTRIBUTES, new String[]{"inPosition", "inTexcoord"}); + shader.put(UNIFORMS, new String[]{"mvpMatrix", "otexture", "texture", "mask", "color", "preview"}); + result.put("blitWithMask_masking", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); shader.put(VERTEX, PAINT_BLIT_VSH); shader.put(FRAGMENT, PAINT_COMPOSITEWITHMASK_FSH); @@ -410,6 +478,13 @@ public class ShaderSet { shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "mask", "color"}); result.put("blitWithMaskEraser", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); + shader.put(VERTEX, PAINT_BLIT_VSH); + shader.put(FRAGMENT, PAINT_MASKING_BLITWITHMASKERASER_FSH); + shader.put(ATTRIBUTES, new String[]{"inPosition", "inTexcoord"}); + shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "otexture", "preview", "mask", "color"}); + result.put("blitWithMaskEraser_masking", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); shader.put(VERTEX, PAINT_BLIT_VSH); shader.put(FRAGMENT, PAINT_COMPOSITEWITHMASKERASER_FSH); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java index 3af3afc32..a67902451 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java @@ -11,4 +11,8 @@ public class Swatch { this.colorLocation = colorLocation; this.brushWeight = brushWeight; } + + public Swatch clone() { + return new Swatch(color, colorLocation, brushWeight); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java index 15b35a048..d584fba2c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java @@ -2,6 +2,7 @@ package org.telegram.ui.Components.Paint.Views; import android.content.Context; import android.graphics.Canvas; +import android.util.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java index 0ac98ccf3..b20f44e8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java @@ -187,7 +187,7 @@ public class EntityView extends FrameLayout { scale(d / pd); } double angleDiff = Math.atan2(y1 - y2, x1 - x2) - Math.atan2(previousLocationY - previousLocationY2, previousLocationX - previousLocationX2); - rotate(this.angle + (float) Math.toDegrees(angleDiff) - delegate.getCropRotation()); + rotate(this.angle + (float) Math.toDegrees(angleDiff)); } previousLocationX = x1; @@ -936,7 +936,7 @@ public class EntityView extends FrameLayout { angle = (float) Math.atan2(y - pos[1], x - pos[0]); } - rotate((float) Math.toDegrees(angle) - delegate.getCropRotation()); + rotate((float) Math.toDegrees(angle)); previousLocationX = x; previousLocationY = y; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java index 4f80d8799..6c42bb363 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java @@ -1,12 +1,13 @@ package org.telegram.ui.Components.Paint.Views; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; -import android.content.DialogInterface; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -16,18 +17,16 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.SweepGradient; import android.graphics.drawable.GradientDrawable; -import android.location.Address; -import android.location.Geocoder; import android.os.Build; import android.os.Looper; import android.text.Layout; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.TypedValue; @@ -36,6 +35,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewParent; import android.view.WindowManager; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; @@ -53,14 +53,12 @@ import com.google.android.gms.vision.face.Face; import com.google.android.gms.vision.face.FaceDetector; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.ImageLoader; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; @@ -72,7 +70,6 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.TLRPC; -import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; @@ -82,6 +79,7 @@ import org.telegram.ui.BubbleActivity; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.ChatActivityEnterViewAnimatedIconView; import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -102,16 +100,11 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.Size; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.SizeNotifierFrameLayoutPhoto; -import org.telegram.ui.Components.StickerMasksAlert; import org.telegram.ui.Components.ThanosEffect; import org.telegram.ui.PhotoViewer; import org.telegram.ui.Stories.recorder.EmojiBottomSheet; -import org.telegram.ui.Stories.recorder.PaintView; -import org.telegram.ui.ThemePreviewActivity; -import org.telegram.ui.WallpapersListActivity; import java.io.File; -import java.io.FileOutputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; @@ -252,8 +245,6 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh return -9539985; } else if (key == Theme.key_chat_emojiPanelIcon) { return -9539985; -// } else if (key == Theme.key_chat_emojiPanelIconSelected) { -// return -10177041; } else if (key == Theme.key_windowBackgroundWhiteBlackText) { return -1; } else if (key == Theme.key_featuredStickers_addedIcon) { @@ -274,6 +265,16 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh return 0x2E878787; } else if (key == Theme.key_windowBackgroundGray) { return 0xFF0D0D0D; + } else if (key == Theme.key_fastScrollInactive) { + return -12500671; + } else if (key == Theme.key_fastScrollActive) { + return -13133079; + } else if (key == Theme.key_fastScrollText) { + return 0xffffffff; + } else if (key == Theme.key_windowBackgroundWhite) { + return -15198183; + } else if (key == Theme.key_divider) { + return 0xFF000000; } if (resourcesProvider != null) { @@ -405,7 +406,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh { setWillNotDraw(false); - linePaint.setStrokeWidth(AndroidUtilities.dp(2)); + linePaint.setStrokeWidth(dp(2)); linePaint.setStyle(Paint.Style.STROKE); linePaint.setColor(Color.WHITE); } @@ -527,13 +528,13 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh addView(selectionContainerView); topLayout = new FrameLayout(context); - topLayout.setPadding(AndroidUtilities.dp(12), AndroidUtilities.dp(12), AndroidUtilities.dp(12), AndroidUtilities.dp(12)); - topLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int [] {0xff000000, 0x00000000} )); + topLayout.setPadding(dp(12), dp(12), dp(12), dp(12)); + topLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[]{0xff000000, 0x00000000})); addView(topLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP)); undoButton = new ImageView(context); undoButton.setImageResource(R.drawable.photo_undo2); - undoButton.setPadding(AndroidUtilities.dp(3), AndroidUtilities.dp(3), AndroidUtilities.dp(3), AndroidUtilities.dp(3)); + undoButton.setPadding(dp(3), dp(3), dp(3), dp(3)); undoButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); undoButton.setOnClickListener(v -> { if (renderView != null && renderView.getCurrentBrush() instanceof Brush.Shape) { @@ -551,7 +552,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh zoomOutButton = new LinearLayout(context); zoomOutButton.setOrientation(LinearLayout.HORIZONTAL); zoomOutButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - zoomOutButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + zoomOutButton.setPadding(dp(8), 0, dp(8), 0); zoomOutText = new TextView(context); zoomOutText.setTextColor(Color.WHITE); zoomOutText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); @@ -569,7 +570,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh undoAllButton = new TextView(context); undoAllButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - undoAllButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + undoAllButton.setPadding(dp(8), 0, dp(8), 0); undoAllButton.setText(LocaleController.getString(R.string.PhotoEditorClearAll)); undoAllButton.setGravity(Gravity.CENTER_VERTICAL); undoAllButton.setTextColor(Color.WHITE); @@ -594,7 +595,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh cancelTextButton = new TextView(context); cancelTextButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); cancelTextButton.setText(LocaleController.getString(R.string.Clear)); - cancelTextButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + cancelTextButton.setPadding(dp(8), 0, dp(8), 0); cancelTextButton.setGravity(Gravity.CENTER_VERTICAL); cancelTextButton.setTextColor(Color.WHITE); cancelTextButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); @@ -616,7 +617,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh doneTextButton = new TextView(context); doneTextButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); doneTextButton.setText(LocaleController.getString(R.string.Done)); - doneTextButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + doneTextButton.setPadding(dp(8), 0, dp(8), 0); doneTextButton.setGravity(Gravity.CENTER_VERTICAL); doneTextButton.setTextColor(Color.WHITE); doneTextButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); @@ -635,7 +636,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh { setWillNotDraw(false); colorPickerRainbowPaint.setStyle(Paint.Style.STROKE); - colorPickerRainbowPaint.setStrokeWidth(AndroidUtilities.dp(2)); + colorPickerRainbowPaint.setStrokeWidth(dp(2)); } private void checkRainbow(float cx, float cy) { @@ -671,12 +672,12 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh ViewGroup barView = getBarView(); AndroidUtilities.rectTmp.set( - AndroidUtilities.lerp(barView.getLeft(), colorsListView.getLeft(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getTop(), colorsListView.getTop(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getRight(), colorsListView.getRight(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getBottom(), colorsListView.getBottom(), toolsTransformProgress) + AndroidUtilities.lerp(barView.getLeft(), colorsListView.getLeft(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getTop(), colorsListView.getTop(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getRight(), colorsListView.getRight(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getBottom(), colorsListView.getBottom(), toolsTransformProgress) ); - final float radius = AndroidUtilities.lerp(AndroidUtilities.dp(32), AndroidUtilities.dp(24), toolsTransformProgress); + final float radius = AndroidUtilities.lerp(dp(32), dp(24), toolsTransformProgress); canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, toolsPaint); if (barView != null && barView.getChildCount() >= 1 && toolsTransformProgress != 1f) { @@ -715,10 +716,10 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh } checkRainbow(cx, cy); - float rad = Math.min(childWidth, childHeight) / 2f - AndroidUtilities.dp(0.5f); + float rad = Math.min(childWidth, childHeight) / 2f - dp(0.5f); if (colorsListView != null && colorsListView.getChildCount() > 0) { View animateToView = colorsListView.getChildAt(0); - rad = AndroidUtilities.lerp(rad, Math.min(animateToView.getWidth() - animateToView.getPaddingLeft() - animateToView.getPaddingRight(), animateToView.getHeight() - animateToView.getPaddingTop() - animateToView.getPaddingBottom()) / 2f - AndroidUtilities.dp(2f), toolsTransformProgress); + rad = AndroidUtilities.lerp(rad, Math.min(animateToView.getWidth() - animateToView.getPaddingLeft() - animateToView.getPaddingRight(), animateToView.getHeight() - animateToView.getPaddingTop() - animateToView.getPaddingBottom()) / 2f - dp(2f), toolsTransformProgress); } AndroidUtilities.rectTmp.set(cx - rad, cy - rad, cx + rad, cy + rad); canvas.drawArc(AndroidUtilities.rectTmp, 0, 360, false, colorPickerRainbowPaint); @@ -728,15 +729,15 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh colorSwatchOutlinePaint.setColor(colorCircle); colorSwatchOutlinePaint.setAlpha((int) (0xFF * child.getAlpha())); - float rad2 = rad - AndroidUtilities.dp(3f); + float rad2 = rad - dp(3f); if (colorsListView != null && colorsListView.getSelectedColorIndex() != 0) { - rad2 = AndroidUtilities.lerp(rad - AndroidUtilities.dp(3f), rad + AndroidUtilities.dp(2), toolsTransformProgress); + rad2 = AndroidUtilities.lerp(rad - dp(3f), rad + dp(2), toolsTransformProgress); } PaintColorsListView.drawColorCircle(canvas, cx, cy, rad2, colorSwatchPaint.getColor()); if (colorsListView != null && colorsListView.getSelectedColorIndex() == 0) { colorSwatchOutlinePaint.setAlpha((int) (colorSwatchOutlinePaint.getAlpha() * toolsTransformProgress * child.getAlpha())); - canvas.drawCircle(cx, cy, rad - (AndroidUtilities.dp(3f) + colorSwatchOutlinePaint.getStrokeWidth()) * (1f - toolsTransformProgress), colorSwatchOutlinePaint); + canvas.drawCircle(cx, cy, rad - (dp(3f) + colorSwatchOutlinePaint.getStrokeWidth()) * (1f - toolsTransformProgress), colorSwatchOutlinePaint); } } @@ -744,19 +745,19 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh } } }; - bottomLayout.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), 0); - bottomLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int [] {0x00000000, 0x80000000} )); + bottomLayout.setPadding(dp(8), dp(8), dp(8), 0); + bottomLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[]{0x00000000, 0x80000000})); addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44 + 60, Gravity.BOTTOM)); paintToolsView = new PaintToolsView(context, originalBitmap != null); - paintToolsView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + paintToolsView.setPadding(dp(16), 0, dp(16), 0); paintToolsView.setDelegate(this); // paintToolsView.setSelectedIndex(MathUtils.clamp(palette.getCurrentBrush(), 0, Brush.BRUSHES_LIST.size()) + 1); paintToolsView.setSelectedIndex(1); bottomLayout.addView(paintToolsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); textOptionsView = new PaintTextOptionsView(context); - textOptionsView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + textOptionsView.setPadding(dp(16), 0, dp(16), 0); textOptionsView.setVisibility(GONE); textOptionsView.setDelegate(this); textOptionsView.setAlignment(PersistColorPalette.getInstance(currentAccount).getCurrentAlignment()); @@ -788,7 +789,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh AndroidUtilities.lerp(yOffset + AndroidUtilities.rectTmp.top, typefaceListView.getTop() - typefaceListView.getTranslationY(), typefaceMenuTransformProgress), AndroidUtilities.lerp(AndroidUtilities.rectTmp.right, typefaceListView.getRight(), typefaceMenuTransformProgress), AndroidUtilities.lerp(yOffset + AndroidUtilities.rectTmp.bottom, typefaceListView.getBottom() - typefaceListView.getTranslationY(), typefaceMenuTransformProgress)); - float rad = AndroidUtilities.dp(AndroidUtilities.lerp(32, 16, typefaceMenuTransformProgress)); + float rad = dp(AndroidUtilities.lerp(32, 16, typefaceMenuTransformProgress)); int alpha = typefaceMenuBackgroundPaint.getAlpha(); typefaceMenuBackgroundPaint.setAlpha((int) (alpha * typefaceMenuTransformProgress)); @@ -813,7 +814,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh typefaceMenuOutlinePaint.setStyle(Paint.Style.STROKE); typefaceMenuOutlinePaint.setColor(0x66FFFFFF); - typefaceMenuOutlinePaint.setStrokeWidth(Math.max(2, AndroidUtilities.dp(1))); + typefaceMenuOutlinePaint.setStrokeWidth(Math.max(2, dp(1))); typefaceMenuBackgroundPaint.setColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); @@ -824,14 +825,14 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh public void draw(Canvas c) { ViewGroup barView = getBarView(); AndroidUtilities.rectTmp.set( - AndroidUtilities.lerp(barView.getLeft() - getLeft(), 0, toolsTransformProgress), - AndroidUtilities.lerp(barView.getTop() - getTop(), 0, toolsTransformProgress), - AndroidUtilities.lerp(barView.getRight() - getLeft(), getWidth(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getBottom() - getTop(), getHeight(), toolsTransformProgress) + AndroidUtilities.lerp(barView.getLeft() - getLeft(), 0, toolsTransformProgress), + AndroidUtilities.lerp(barView.getTop() - getTop(), 0, toolsTransformProgress), + AndroidUtilities.lerp(barView.getRight() - getLeft(), getWidth(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getBottom() - getTop(), getHeight(), toolsTransformProgress) ); path.rewind(); - path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(32), AndroidUtilities.dp(32), Path.Direction.CW); + path.addRoundRect(AndroidUtilities.rectTmp, dp(32), dp(32), Path.Direction.CW); c.save(); c.clipPath(path); @@ -850,12 +851,12 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh setupTabsLayout(context); cancelButton = new PaintCancelView(context); - cancelButton.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + cancelButton.setPadding(dp(8), dp(8), dp(8), dp(8)); cancelButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); bottomLayout.addView(cancelButton, LayoutHelper.createFrame(32, 32, Gravity.BOTTOM | Gravity.LEFT, 12, 0, 0, 4)); doneButton = new PaintDoneView(context); - doneButton.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + doneButton.setPadding(dp(8), dp(8), dp(8), dp(8)); doneButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); doneButton.setOnClickListener(v -> { if (isColorListShown) { @@ -934,7 +935,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh weightChooserView.setRenderView(renderView); weightChooserView.setValueOverride(weightDefaultValueOverride); colorSwatch.brushWeight = weightDefaultValueOverride.get(); - weightChooserView.setOnUpdate(()-> { + weightChooserView.setOnUpdate(() -> { setCurrentSwatch(colorSwatch, true); PersistColorPalette.getInstance(currentAccount).setCurrentWeight(colorSwatch.brushWeight); }); @@ -944,7 +945,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh addView(pipetteContainerLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); colorSwatchOutlinePaint.setStyle(Paint.Style.STROKE); - colorSwatchOutlinePaint.setStrokeWidth(AndroidUtilities.dp(2)); + colorSwatchOutlinePaint.setStrokeWidth(dp(2)); setCurrentSwatch(colorSwatch, true); // onBrushSelected(Brush.BRUSHES_LIST.get(MathUtils.clamp(palette.getCurrentBrush(), 0, Brush.BRUSHES_LIST.size()))); @@ -952,10 +953,18 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh updateColors(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - setSystemGestureExclusionRects(Arrays.asList(new Rect(0, (int) (AndroidUtilities.displaySize.y * .35f), AndroidUtilities.dp(100), (int) (AndroidUtilities.displaySize.y * .65)))); + setSystemGestureExclusionRects(Arrays.asList(new Rect(0, (int) (AndroidUtilities.displaySize.y * .35f), dp(100), (int) (AndroidUtilities.displaySize.y * .65)))); } } + private boolean drawShadow; + + public void setDrawShadow(boolean drawShadow) { + this.drawShadow = drawShadow; + invalidate(); + setClipChildren(!drawShadow); + } + private void setNewColor(int color) { int wasColor = colorSwatch.color; colorSwatch.color = color; @@ -1184,10 +1193,29 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh return changed; } + private final AnimatedFloat shadowAlpha = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final Paint shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); { + clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean restore = false; - if ((child == renderView || child == renderInputView || child == entitiesView || child == selectionContainerView) && currentCropState != null) { + if (child == entitiesView) { + float shadowAlpha = this.shadowAlpha.set(LPhotoPaintView.this.drawShadow); + if (shadowAlpha > 0) { + shadowPaint.setShadowLayer(dp(24 * shadowAlpha), 0, 0, Theme.multAlpha(0x40FFFFFF, shadowAlpha)); + shadowPaint.setColor(0); + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + canvas.translate(entitiesView.getX(), entitiesView.getY()); + canvas.scale(entitiesView.getScaleX(), entitiesView.getScaleY(), entitiesView.getWidth() / 2f, entitiesView.getHeight() / 2f); + canvas.drawRect(0, 0, entitiesView.getWidth(), entitiesView.getHeight(), shadowPaint); + canvas.drawRect(0, 0, entitiesView.getWidth(), entitiesView.getHeight(), clearPaint); + canvas.restore(); + } + } + if ((child == renderView || child == renderInputView || child == entitiesView && entitiesView.getClipChildren() || child == selectionContainerView && selectionContainerView.getClipChildren()) && currentCropState != null) { canvas.save(); int status = (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0); @@ -1206,7 +1234,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh int w = (int) (vw * currentCropState.cropPw * child.getScaleX() / currentCropState.cropScale); int h = (int) (vh * currentCropState.cropPh * child.getScaleY() / currentCropState.cropScale); float x = (float) Math.ceil((getMeasuredWidth() - w) / 2f) + transformX; - float y = (getMeasuredHeight() - emojiPadding - actionBarHeight2 - AndroidUtilities.dp(48) + getAdditionalBottom() - h) / 2f + AndroidUtilities.dp(8) + status + transformY; + float y = (getMeasuredHeight() - emojiPadding - actionBarHeight2 - dp(48) + getAdditionalBottom() - h) / 2f + dp(8) + status + transformY; canvas.clipRect(Math.max(0, x), Math.max(0, y), Math.min(x + w, getMeasuredWidth()), Math.min(getMeasuredHeight(), y + h)); restore = true; @@ -1227,7 +1255,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); { - linePaint.setStrokeWidth(AndroidUtilities.dp(2)); + linePaint.setStrokeWidth(dp(2)); linePaint.setStyle(Paint.Style.STROKE); linePaint.setStrokeCap(Paint.Cap.ROUND); @@ -1241,7 +1269,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh TextView selectedTab = (TextView) getChildAt(tabsSelectedIndex); TextView newSelectedTab = tabsNewSelectedIndex != -1 ? (TextView) getChildAt(tabsNewSelectedIndex) : null; linePaint.setColor(selectedTab.getCurrentTextColor()); - float y = selectedTab.getY() + selectedTab.getHeight() - selectedTab.getPaddingBottom() + AndroidUtilities.dp(3); + float y = selectedTab.getY() + selectedTab.getHeight() - selectedTab.getPaddingBottom() + dp(3); Layout layout = selectedTab.getLayout(); Layout newLayout = newSelectedTab != null ? newSelectedTab.getLayout() : null; float pr = newLayout == null ? 0 : CubicBezierInterpolator.DEFAULT.getInterpolation(tabsSelectionProgress); @@ -1257,7 +1285,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh drawTab = new TextView(context); drawTab.setText(LocaleController.getString(R.string.PhotoEditorDraw).toUpperCase()); drawTab.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - drawTab.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + drawTab.setPadding(0, dp(8), 0, dp(8)); drawTab.setTextColor(Color.WHITE); drawTab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); drawTab.setGravity(Gravity.CENTER_HORIZONTAL); @@ -1275,7 +1303,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh stickerTab = new TextView(context); stickerTab.setText(LocaleController.getString(R.string.PhotoEditorSticker).toUpperCase()); stickerTab.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - stickerTab.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + stickerTab.setPadding(0, dp(8), 0, dp(8)); stickerTab.setOnClickListener(v -> openStickersView()); stickerTab.setTextColor(Color.WHITE); stickerTab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); @@ -1288,7 +1316,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh textTab = new TextView(context); textTab.setText(LocaleController.getString(R.string.PhotoEditorText).toUpperCase()); textTab.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - textTab.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + textTab.setPadding(0, dp(8), 0, dp(8)); textTab.setTextColor(Color.WHITE); textTab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textTab.setGravity(Gravity.CENTER_HORIZONTAL); @@ -1345,13 +1373,13 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh float scale = 0.6f + 0.4f * (1f - pr); view.setScaleX(scale); view.setScaleY(scale); - view.setTranslationY(AndroidUtilities.dp(16) * Math.min(pr, 0.25f) / 0.25f); + view.setTranslationY(dp(16) * Math.min(pr, 0.25f) / 0.25f); view.setAlpha(1f - Math.min(pr, 0.25f) / 0.25f); scale = 0.6f + 0.4f * pr; newView.setScaleX(scale); newView.setScaleY(scale); - newView.setTranslationY(-AndroidUtilities.dp(16) * Math.min(1f - pr, 0.25f) / 0.25f); + newView.setTranslationY(-dp(16) * Math.min(1f - pr, 0.25f) / 0.25f); newView.setAlpha(1f - Math.min(1f - pr, 0.25f) / 0.25f); } }); @@ -1399,7 +1427,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh detectFaces(); } }, 350); - EmojiBottomSheet emojiBottomSheet = new EmojiBottomSheet(getContext(), false, resourcesProvider) { + EmojiBottomSheet emojiBottomSheet = new EmojiBottomSheet(getContext(), false, resourcesProvider, false) { @Override public boolean canShowWidget(Integer id) { return id == WIDGET_PHOTO; @@ -1410,6 +1438,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh if (isGif) { stickerView.setScale(1.5f); } + return true; }); emojiBottomSheet.whenWidgetSelected(widget -> { if (widget == EmojiBottomSheet.WIDGET_PHOTO) { @@ -1573,13 +1602,13 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh float bitmapW; float bitmapH; int fullHeight = AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - getAdditionalTop() - getAdditionalBottom(); - int maxHeight = fullHeight - AndroidUtilities.dp(48); + int maxHeight = fullHeight - dp(48); if (bitmapToEdit != null) { bitmapW = bitmapToEdit.getWidth(); bitmapH = bitmapToEdit.getHeight(); } else { bitmapW = width; - bitmapH = height - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48); + bitmapH = height - ActionBar.getCurrentActionBarHeight() - dp(48); } float renderWidth = width; @@ -1609,18 +1638,18 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh int keyboardPad = Math.max(getPKeyboardHeight(), emojiPadding); measureChild(overlayLayout, widthMeasureSpec, MeasureSpec.makeMeasureSpec(height - keyboardPad, MeasureSpec.EXACTLY)); - topLayout.setPadding(topLayout.getPaddingLeft(), AndroidUtilities.dp(12) + AndroidUtilities.statusBarHeight, topLayout.getPaddingRight(), topLayout.getPaddingBottom()); + topLayout.setPadding(topLayout.getPaddingLeft(), dp(12) + AndroidUtilities.statusBarHeight, topLayout.getPaddingRight(), topLayout.getPaddingBottom()); measureChild(topLayout, widthMeasureSpec, heightMeasureSpec); ignoreLayout = false; int keyboardSize = 0; - if (!waitingForKeyboardOpen && keyboardSize <= AndroidUtilities.dp(20) && !emojiViewVisible && !isAnimatePopupClosing) { + if (!waitingForKeyboardOpen && keyboardSize <= dp(20) && !emojiViewVisible && !isAnimatePopupClosing) { ignoreLayout = true; hideEmojiView(); ignoreLayout = false; } - if (keyboardSize <= AndroidUtilities.dp(20)) { + if (keyboardSize <= dp(20)) { } else { hideEmojiView(); @@ -1657,7 +1686,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh int actionBarHeight2 = actionBarHeight + status; int x = (int) Math.ceil((width - renderView.getMeasuredWidth()) / 2f); - int y = (height - actionBarHeight2 - AndroidUtilities.dp(48) - renderView.getMeasuredHeight()) / 2 + AndroidUtilities.dp(8) + status + (getAdditionalTop() - getAdditionalBottom()) / 2; + int y = (height - actionBarHeight2 - dp(48) - renderView.getMeasuredHeight()) / 2 + dp(8) + status + (getAdditionalTop() - getAdditionalBottom()) / 2; renderView.layout(x, y, x + renderView.getMeasuredWidth(), y + renderView.getMeasuredHeight()); renderInputView.layout(x, y, x + renderInputView.getMeasuredWidth(), y + renderInputView.getMeasuredHeight()); @@ -2059,7 +2088,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh } float x2 = (ev.getX() - renderView.getTranslationX() - getMeasuredWidth() / 2f) / renderView.getScaleX(); - float y2 = (ev.getY() - renderView.getTranslationY() - getMeasuredHeight() / 2f + AndroidUtilities.dp(32) - (getAdditionalTop() - getAdditionalBottom()) / 2f) / renderView.getScaleY(); + float y2 = (ev.getY() - renderView.getTranslationY() - getMeasuredHeight() / 2f + dp(32) - (getAdditionalTop() - getAdditionalBottom()) / 2f) / renderView.getScaleY(); float rotation = (float) Math.toRadians(-renderView.getRotation()); float x = (float) (x2 * Math.cos(rotation) - y2 * Math.sin(rotation)) + renderView.getMeasuredWidth() / 2f; float y = (float) (x2 * Math.sin(rotation) + y2 * Math.cos(rotation)) + renderView.getMeasuredHeight() / 2f; @@ -2073,12 +2102,12 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh @Override public int getAdditionalTop() { - return AndroidUtilities.dp(48); + return dp(48); } @Override public int getAdditionalBottom() { - return AndroidUtilities.dp(24); + return dp(24); } @Override @@ -2315,7 +2344,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh float scale = 0.6f + 0.4f * (1f - toolsTransformProgress); barView.setScaleX(scale); barView.setScaleY(scale); - barView.setTranslationY(AndroidUtilities.dp(16) * Math.min(toolsTransformProgress, 0.25f) / 0.25f); + barView.setTranslationY(dp(16) * Math.min(toolsTransformProgress, 0.25f) / 0.25f); barView.setAlpha(1f - Math.min(toolsTransformProgress, 0.25f) / 0.25f); colorsListView.setProgress(toolsTransformProgress, show); @@ -2323,13 +2352,13 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh doneButton.setProgress(toolsTransformProgress); cancelButton.setProgress(toolsTransformProgress); - tabsLayout.setTranslationY(AndroidUtilities.dp(32) * toolsTransformProgress); + tabsLayout.setTranslationY(dp(32) * toolsTransformProgress); // if (adjustPanLayoutHelper.animationInProgress()) { // moveBottomLayout[0] = false; // } if (moveBottomLayout[0]) { float progress = show ? toolsTransformProgress : 1f - toolsTransformProgress; - bottomLayout.setTranslationY(bottomLayoutTranslationY - AndroidUtilities.dp(40) * progress * (show ? 1 : -1)); + bottomLayout.setTranslationY(bottomLayoutTranslationY - dp(40) * progress * (show ? 1 : -1)); } bottomLayout.invalidate(); @@ -2569,11 +2598,11 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh private void setTextType(int type) { selectedTextType = type; if (currentEntityView instanceof TextPaintView) { - if (type == 0 && colorSwatch.color == Color.WHITE) { - setNewColor(Color.BLACK); - } else if ((type == 1 || type == 2) && colorSwatch.color == Color.BLACK) { - setNewColor(Color.WHITE); - } +// if (type == 0 && colorSwatch.color == Color.WHITE) { +// setNewColor(Color.BLACK); +// } else if ((type == 1 || type == 2) && colorSwatch.color == Color.BLACK) { +// setNewColor(Color.WHITE); +// } ((TextPaintView) currentEntityView).setType(type); } PersistColorPalette.getInstance(currentAccount).setCurrentTextType(type); @@ -2678,7 +2707,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh private void showMenuForEntity(final EntityView entityView) { int[] pos = getCenterLocationInWindow(entityView); int x = pos[0]; - int y = pos[1] - AndroidUtilities.dp(32); + int y = pos[1] - dp(32); showPopup(() -> { LinearLayout parent = new LinearLayout(getContext()); @@ -2688,7 +2717,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh deleteView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); deleteView.setBackground(Theme.getSelectorDrawable(false)); deleteView.setGravity(Gravity.CENTER_VERTICAL); - deleteView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(14), 0); + deleteView.setPadding(dp(16), 0, dp(14), 0); deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); deleteView.setTag(0); deleteView.setText(LocaleController.getString("PaintDelete", R.string.PaintDelete)); @@ -2707,7 +2736,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh editView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); editView.setBackground(Theme.getSelectorDrawable(false)); editView.setGravity(Gravity.CENTER_VERTICAL); - editView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + editView.setPadding(dp(16), 0, dp(16), 0); editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); editView.setEllipsize(TextUtils.TruncateAt.END); editView.setTag(1); @@ -2728,7 +2757,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh flipView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); flipView.setGravity(Gravity.CENTER_VERTICAL); flipView.setEllipsize(TextUtils.TruncateAt.END); - flipView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + flipView.setPadding(dp(14), 0, dp(16), 0); flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); flipView.setTag(2); flipView.setText(LocaleController.getString("Flip", R.string.Flip)); @@ -2748,7 +2777,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh duplicateView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); duplicateView.setGravity(Gravity.CENTER_VERTICAL); duplicateView.setEllipsize(TextUtils.TruncateAt.END); - duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + duplicateView.setPadding(dp(14), 0, dp(16), 0); duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); duplicateView.setTag(2); duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate)); @@ -2769,7 +2798,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh cutView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); cutView.setGravity(Gravity.CENTER_VERTICAL); cutView.setEllipsize(TextUtils.TruncateAt.END); - cutView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + cutView.setPadding(dp(14), 0, dp(16), 0); cutView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); cutView.setTag(5); cutView.setText(LocaleController.getString(photoView.isSegmented() ? R.string.SegmentationUndoCutOut : R.string.SegmentationCutOut)); @@ -2904,7 +2933,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh popupWindow.setOnDismissListener(() -> popupLayout.removeInnerViews()); } - popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST)); + popupLayout.measure(MeasureSpec.makeMeasureSpec(dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(1000), MeasureSpec.AT_MOST)); popupWindow.setFocusable(true); @@ -3129,17 +3158,52 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh return getCenterLocationInWindow(entityView); } - private int[] pos = new int[2]; + private Matrix matrix = new Matrix(); + private float[] position = new float[2]; + private int[] pos2 = new int[2]; private int[] getCenterLocationInWindow(View view) { - view.getLocationInWindow(pos); - float rotation = (float) Math.toRadians(view.getRotation() + (currentCropState != null ? currentCropState.cropRotate + currentCropState.transformRotation : 0)); - float width = view.getWidth() * view.getScaleX() * entitiesView.getScaleX(); - float height = view.getHeight() * view.getScaleY() * entitiesView.getScaleY(); - float px = (float) (width * Math.cos(rotation) - height * Math.sin(rotation)); - float py = (float) (width * Math.sin(rotation) + height * Math.cos(rotation)); - pos[0] += px / 2; - pos[1] += py / 2; - return pos; + // code taken from android transformFromViewToWindowSpace source code + position[0] = view.getWidth() / 2f; + position[1] = view.getHeight() / 2f; + + view.getMatrix().mapPoints(position); + position[0] += view.getLeft(); + position[1] += view.getTop(); + ViewParent viewParent = view.getParent(); + while (viewParent instanceof View) { + final View nextView = (View) viewParent; + position[0] -= nextView.getScrollX(); + position[1] -= nextView.getScrollY(); + nextView.getMatrix().mapPoints(position); + position[0] += nextView.getLeft(); + position[1] += nextView.getTop(); + viewParent = nextView.getParent(); + } + + pos2[0] = Math.round(position[0]); + pos2[1] = Math.round(position[1]); + + float x2 = (pos2[0] - AndroidUtilities.displaySize.x / 2f); + float y2 = (pos2[1] - AndroidUtilities.displaySize.y / 2f); + float rotation = (float) Math.toRadians(-entitiesView.getRotation()); + pos2[0] = (int) (x2 * Math.cos(rotation) - y2 * Math.sin(rotation)) + AndroidUtilities.displaySize.x / 2; + pos2[1] = (int) (x2 * Math.sin(rotation) + y2 * Math.cos(rotation)) + AndroidUtilities.displaySize.y / 2; + + return pos2; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean r = false; +// if (entitiesView != null && !entitiesView.getClipChildren() && ev.getPointerCount() > 1) { +// MotionEvent transformedEvent = MotionEvent.obtain(ev); +// transformedEvent.offsetLocation(-entitiesView.getLeft(), -entitiesView.getTop()); +// entitiesView.getMatrix().invert(matrix); +// transformedEvent.transform(matrix); +// r = entitiesView.dispatchTouchEvent(transformedEvent) || r; +// transformedEvent.recycle(); +// } + return super.dispatchTouchEvent(ev) || r; } @Override @@ -3227,16 +3291,16 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh if (keyboardHeight <= 0) { if (AndroidUtilities.isTablet()) { - keyboardHeight = AndroidUtilities.dp(150); + keyboardHeight = dp(150); } else { - keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", AndroidUtilities.dp(200)); + keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", dp(200)); } } if (keyboardHeightLand <= 0) { if (AndroidUtilities.isTablet()) { - keyboardHeightLand = AndroidUtilities.dp(150); + keyboardHeightLand = dp(150); } else { - keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", AndroidUtilities.dp(200)); + keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", dp(200)); } } int currentHeight = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight; @@ -3399,7 +3463,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh @Override public void onSizeChanged(int height, boolean isWidthGreater) { - if (height > AndroidUtilities.dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + if (height > dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { if (isWidthGreater) { keyboardHeightLand = height; MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height_land3", keyboardHeightLand).commit(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java new file mode 100644 index 000000000..84598eaf7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java @@ -0,0 +1,462 @@ +package org.telegram.ui.Components.Paint.Views; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Build; +import android.os.Looper; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Animation; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DispatchQueue; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.BubbleActivity; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Paint.Brush; +import org.telegram.ui.Components.Paint.Painting; +import org.telegram.ui.Components.Paint.PersistColorPalette; +import org.telegram.ui.Components.Paint.RenderView; +import org.telegram.ui.Components.Paint.Swatch; +import org.telegram.ui.Components.Paint.UndoStore; +import org.telegram.ui.Components.Size; + +import java.util.ArrayList; + +public class MaskPaintView extends FrameLayout { + + private int currentAccount; + + private UndoStore undoStore; + private DispatchQueue queue; + + private MediaController.CropState currentCropState; + private final RenderView renderView; + private Bitmap bitmapToEdit; + private int orientation; + + private boolean inBubbleMode; + + public final FrameLayout buttonsLayout; + public final TextView cancelButton; + public final TextView doneButton; + + public PaintWeightChooserView weightChooserView; + private PaintWeightChooserView.ValueOverride weightDefaultValueOverride = new PaintWeightChooserView.ValueOverride() { + @Override + public float get() { + Brush brush = renderView.getCurrentBrush(); + if (brush == null) { + return PersistColorPalette.getInstance(currentAccount).getCurrentWeight(); + } + return PersistColorPalette.getInstance(currentAccount).getWeight("-1", brush.getDefaultWeight()); + } + + @Override + public void set(float val) { + PersistColorPalette.getInstance(currentAccount).setWeight("-1", val); + renderView.setBrushSize(val); + } + }; + + public MaskPaintView(Context context, int currentAccount, Bitmap bitmapToEdit, Bitmap bitmap, int orientation, MediaController.CropState cropState) { + super(context); + + this.currentAccount = currentAccount; + + inBubbleMode = context instanceof BubbleActivity; + + undoStore = new UndoStore(); + undoStore.setDelegate(new UndoStore.UndoStoreDelegate() { + @Override + public void historyChanged() { + + } + }); + queue = new DispatchQueue("MaskPaint"); + + this.currentCropState = cropState; + this.bitmapToEdit = bitmapToEdit; + this.orientation = orientation; + renderView = new RenderView(context, new Painting(getPaintingSize(), bitmap, orientation, null).asMask(), bitmapToEdit, null, null); + renderView.setAlpha(0f); + renderView.setDelegate(new RenderView.RenderViewDelegate() { + @Override + public void onBeganDrawing() { + weightChooserView.setViewHidden(true); + } + + @Override + public void onFinishedDrawing(boolean moved) { + undoStore.getDelegate().historyChanged(); + weightChooserView.setViewHidden(false); + onDrawn(); + } + + @Override + public void onFirstDraw() { + renderView.animate().alpha(1f).setDuration(320).setUpdateListener(MaskPaintView.this::onRenderViewAlphaUpdate).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + } + + @Override + public boolean shouldDraw() { + return true; + } + + @Override + public void resetBrush() { + + } + }); + renderView.setUndoStore(undoStore); + renderView.setQueue(queue); + renderView.setVisibility(View.INVISIBLE); + renderView.setBrush(new Brush.Radial()); + renderView.setBrushSize(weightDefaultValueOverride.get()); + renderView.setColor(0xFFFF0000); + addView(renderView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + + weightChooserView = new PaintWeightChooserView(context); + weightChooserView.setMinMax(0.05f, 1f); + weightChooserView.setBrushWeight(weightDefaultValueOverride.get()); + weightChooserView.setRenderView(renderView); + weightChooserView.setValueOverride(weightDefaultValueOverride); + weightChooserView.setTranslationX(-dp(18)); + weightChooserView.setAlpha(0f); + addView(weightChooserView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + buttonsLayout = new FrameLayout(context); + buttonsLayout.setAlpha(0f); + buttonsLayout.setVisibility(View.GONE); + addView(buttonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44, Gravity.BOTTOM)); + + cancelButton = new TextView(context); + cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + cancelButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + cancelButton.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(Color.WHITE, .15f), Theme.RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE)); + cancelButton.setPadding(dp(28), 0, dp(28), 0); + cancelButton.setText(LocaleController.getString(R.string.Cancel).toUpperCase()); + cancelButton.setTextColor(Color.WHITE); + cancelButton.setGravity(Gravity.CENTER); + buttonsLayout.addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 44, Gravity.LEFT, -8, 0, 0, 0)); + + doneButton = new TextView(context); + doneButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + doneButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + doneButton.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_chat_editMediaButton), .15f), Theme.RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE)); + doneButton.setPadding(dp(28), 0, dp(28), 0); + doneButton.setText(LocaleController.getString(R.string.Save).toUpperCase()); + doneButton.setTextColor(Theme.getColor(Theme.key_chat_editMediaButton)); + doneButton.setGravity(Gravity.CENTER); + buttonsLayout.addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 44, Gravity.RIGHT, 0, 0, -8, 0)); + } + + protected void onDrawn() { + + } + + protected void onRenderViewAlphaUpdate(ValueAnimator animation) { + + } + + public boolean canUndo() { + return undoStore.canUndo(); + } + public boolean undo() { + if (!undoStore.canUndo()) return false; + undoStore.undo(); + return true; + } + + private Size paintingSize; + private Size getPaintingSize() { + if (paintingSize != null) { + return paintingSize; + } + float width = bitmapToEdit.getWidth(); + float height = bitmapToEdit.getHeight(); + + int maxSide = 1280; + Size size = new Size(width, height); + size.width = maxSide; + size.height = (float) Math.floor(size.width * height / width); + if (size.height > maxSide) { + size.height = maxSide; + size.width = (float) Math.floor(size.height * width / height); + } + paintingSize = size; + return size; + } + + private boolean eraser; + public void setEraser(boolean eraser) { + if (this.eraser == eraser) return; + this.eraser = eraser; + renderView.setBrush(eraser ? new Brush.Eraser() : new Brush.Radial()); + } + + private float panTranslationY, scale, inputTransformX, inputTransformY, transformX, transformY, imageWidth, imageHeight; + + public void setTransform(float scale, float trX, float trY, float rotate, float imageWidth, float imageHeight) { + this.scale = scale; + this.imageWidth = imageWidth; + this.imageHeight = imageHeight; + inputTransformX = trX; + inputTransformY = trY; + transformX = trX; + trY += panTranslationY; + transformY = trY; + for (int a = 0; a < 1; a++) { + View view; + float additionlScale = 1.0f; + if (a == 0) { + view = renderView; + } else continue; + float tx; + float ty; + float rotation = rotate; + if (currentCropState != null) { + additionlScale *= currentCropState.cropScale; + + int w = view.getMeasuredWidth(); + int h = view.getMeasuredHeight(); + if (w == 0 || h == 0) { + return; + } + int tr = currentCropState.transformRotation; + int fw = w, rotatedW = w; + int fh = h, rotatedH = h; + if (tr == 90 || tr == 270) { + int temp = fw; + fw = rotatedW = fh; + fh = rotatedH = temp; + } + fw *= currentCropState.cropPw; + fh *= currentCropState.cropPh; + + float sc = Math.max(imageWidth / fw, imageHeight / fh); + additionlScale *= sc; + + tx = trX + currentCropState.cropPx * rotatedW * scale * sc * currentCropState.cropScale; + ty = trY + currentCropState.cropPy * rotatedH * scale * sc * currentCropState.cropScale; + rotation += currentCropState.cropRotate + tr; + } else { + if (a == 0) { + additionlScale *= baseScale; + } + tx = trX; + ty = trY; + } + float finalScale = scale * additionlScale; + if (Float.isNaN(finalScale)) { + finalScale = 1f; + } + view.setScaleX(finalScale); + view.setScaleY(finalScale); + view.setTranslationX(tx); + view.setTranslationY(ty); + view.setRotation(rotation); + view.invalidate(); + } + invalidate(); + } + + public void init() { + renderView.setVisibility(View.VISIBLE); + buttonsLayout.setVisibility(View.VISIBLE); + buttonsLayout.setTranslationY(dp(18)); + buttonsLayout.animate().alpha(1f).translationY(0).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + weightChooserView.animate().alpha(1f).translationX(0).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + } + + private boolean ignoreLayout; + private float baseScale; + + private ArrayList exclusionRects = new ArrayList<>(); + private Rect exclusionRect = new Rect(); + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + ignoreLayout = true; + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(width, height); + + float bitmapW; + float bitmapH; + int fullHeight = AndroidUtilities.displaySize.y; + int maxHeight = fullHeight; + if (bitmapToEdit != null) { + bitmapW = bitmapToEdit.getWidth(); + bitmapH = bitmapToEdit.getHeight(); + } else { + bitmapW = width; + bitmapH = height; + } + + float renderWidth = width; + float renderHeight = (float) Math.floor(renderWidth * bitmapH / bitmapW); + if (renderHeight > maxHeight) { + renderHeight = maxHeight; + renderWidth = (float) Math.floor(renderHeight * bitmapW / bitmapH); + } + + renderView.measure(MeasureSpec.makeMeasureSpec((int) renderWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) renderHeight, MeasureSpec.EXACTLY)); + + baseScale = 1f;//renderWidth / paintingSize.width; + measureChild(weightChooserView, widthMeasureSpec, heightMeasureSpec); + measureChild(buttonsLayout, widthMeasureSpec, heightMeasureSpec); + + ignoreLayout = false; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + exclusionRects.clear(); + exclusionRects.add(exclusionRect); + int h = (int) (getMeasuredHeight() * .3f); + exclusionRect.set(0, (getMeasuredHeight() - h) / 2, dp(20), (getMeasuredHeight() + h) / 2); + setSystemGestureExclusionRects(exclusionRects); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int width = right - left; + int height = bottom - top; + + int status = (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0); + int actionBarHeight = 0; + int actionBarHeight2 = status; + + int x = (int) Math.ceil((width - renderView.getMeasuredWidth()) / 2f); + int y = (height - renderView.getMeasuredHeight()) / 2; + + renderView.layout(x, y, x + renderView.getMeasuredWidth(), y + renderView.getMeasuredHeight()); + int b = bottom - top; + buttonsLayout.layout(0, b - buttonsLayout.getMeasuredHeight(), buttonsLayout.getMeasuredWidth(), b); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + boolean restore = false; + if ((child == renderView) && currentCropState != null) { + canvas.save(); + + int status = (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0); + int actionBarHeight = ActionBar.getCurrentActionBarHeight(); + int actionBarHeight2 = actionBarHeight + status; + + int vw = child.getMeasuredWidth(); + int vh = child.getMeasuredHeight(); + int tr = currentCropState.transformRotation; + if (tr == 90 || tr == 270) { + int temp = vw; + vw = vh; + vh = temp; + } + + int w = (int) (vw * currentCropState.cropPw * child.getScaleX() / currentCropState.cropScale); + int h = (int) (vh * currentCropState.cropPh * child.getScaleY() / currentCropState.cropScale); + float x = (float) Math.ceil((getMeasuredWidth() - w) / 2f) + transformX; + float y = (getMeasuredHeight() - actionBarHeight2 - dp(48) + getAdditionalBottom() - h) / 2f + dp(8) + status + transformY; + + canvas.clipRect(Math.max(0, x), Math.max(0, y), Math.min(x + w, getMeasuredWidth()), Math.min(getMeasuredHeight(), y + h)); + restore = true; + } + boolean result = super.drawChild(canvas, child, drawingTime); + if (restore) { + canvas.restore(); + } + return result; + } + + public boolean onTouch(MotionEvent ev) { + float x2 = (ev.getX() - renderView.getTranslationX() - getMeasuredWidth() / 2f) / renderView.getScaleX(); + float y2 = (ev.getY() - renderView.getTranslationY() - getMeasuredHeight() / 2f) / renderView.getScaleY(); + float rotation = (float) Math.toRadians(-renderView.getRotation()); + float x = (float) (x2 * Math.cos(rotation) - y2 * Math.sin(rotation)) + renderView.getMeasuredWidth() / 2f; + float y = (float) (x2 * Math.sin(rotation) + y2 * Math.cos(rotation)) + renderView.getMeasuredHeight() / 2f; + + MotionEvent event = MotionEvent.obtain(ev); + event.setLocation(x, y); + renderView.onTouch(event); + event.recycle(); + return true; + } + + public Bitmap getBitmap() { + Bitmap resultBitmap = renderView.getResultBitmap(false, false); + if (orientation != 0) { + int w = resultBitmap.getWidth(), h = resultBitmap.getHeight(); + if (orientation / 90 % 2 != 0) { + w = resultBitmap.getHeight(); + h = resultBitmap.getWidth(); + } + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(b); + canvas.translate(w / 2f, h / 2f); + canvas.rotate(-orientation); + AndroidUtilities.rectTmp.set( + -resultBitmap.getWidth() / 2f, + -resultBitmap.getHeight() / 2f, + resultBitmap.getWidth() / 2f, + resultBitmap.getHeight() / 2f + ); + canvas.drawBitmap(resultBitmap, null, AndroidUtilities.rectTmp, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + resultBitmap.recycle(); + resultBitmap = b; + } + return resultBitmap; + } + + public RenderView getRenderView() { + return renderView; + } + + public int getAdditionalTop() { + return 0; // AndroidUtilities.dp(48); + } + + public int getAdditionalBottom() { + return 0; // AndroidUtilities.dp(24); + } + + public void shutdown() { + renderView.shutdown(); + queue.postRunnable(() -> { + Looper looper = Looper.myLooper(); + if (looper != null) { + looper.quit(); + } + }); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java index 1292af8eb..d52c96939 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java @@ -95,7 +95,9 @@ public class PaintWeightChooserView extends View { colorSwatch.brushWeight = weight; } animatedWeight.set(weight, true); - onUpdate.run(); + if (onUpdate != null) { + onUpdate.run(); + } invalidate(); } return isTouchInProgress; @@ -157,6 +159,11 @@ public class PaintWeightChooserView extends View { invalidate(); } + public void setBrushWeight(float brushWeight) { + this.colorSwatch.brushWeight = brushWeight; + invalidate(); + } + public void setDrawCenter(boolean draw) { drawCenter = draw; invalidate(); @@ -264,7 +271,7 @@ public class PaintWeightChooserView extends View { false ); - if (drawCenter && showProgress != 0f && showPreview) { + if (drawCenter && showProgress != 0f && showPreview && renderView != null) { float cx = getWidth() / 2f, cy = getHeight() / 2f, rad = renderView.brushWeightForSize(weight) * renderView.getCurrentBrush().getScale() * renderView.getCurrentBrush().getPreviewScale(); drawCircleWithShadow(canvas, cx, cy, rad, true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java index 220a68534..98198f7e7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java @@ -71,7 +71,7 @@ public class PhotoView extends EntityView { private int anchor = -1; private boolean mirrored = false; private final AnimatedFloat mirrorT; - private Size baseSize; + public Size baseSize; private boolean overridenSegmented = false; private int orientation, invert; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java index 9963dec73..3efb21341 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java @@ -21,24 +21,40 @@ import org.telegram.ui.Stories.recorder.ButtonWithCounterView; @SuppressLint("ViewConstructor") public class StickerCutOutBtn extends ButtonWithCounterView { + private static final int STATE_CUT_OUT = 0; private static final int STATE_UNDO_CAT = 1; private static final int STATE_CANCEL = 2; + private static final int STATE_ERASE = 3; + private static final int STATE_RESTORE = 4; + private static final int STATE_UNDO = 5; + private static final int STATE_OUTLINE = 6; protected final BlurringShader.StoryBlurDrawer blurDrawer; protected final RectF bounds = new RectF(); private int state; private final StickerMakerView stickerMakerView; + private final Theme.ResourcesProvider resourcesProvider; + public StickerCutOutBtn(StickerMakerView stickerMakerView, Context context, Theme.ResourcesProvider resourcesProvider, BlurringShader.BlurManager blurManager) { super(context, false, resourcesProvider); + this.resourcesProvider = resourcesProvider; this.stickerMakerView = stickerMakerView; blurDrawer = new BlurringShader.StoryBlurDrawer(blurManager, this, BlurringShader.StoryBlurDrawer.BLUR_TYPE_BACKGROUND, true); setWillNotDraw(false); setTextColor(Color.WHITE); setFlickeringLoading(true); text.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - setForeground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); + disableRippleView(); + setForeground(Theme.createRadSelectorDrawable(Theme.multAlpha(Color.WHITE, .08f), 8, 8)); + setPadding(dp(24), 0, dp(24), 0); + } + + public int rad = 8; + public void setRad(int rad) { + this.rad = rad; + setForeground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), rad, rad)); } @Override @@ -51,7 +67,12 @@ public class StickerCutOutBtn extends ButtonWithCounterView { @Override protected void onDraw(Canvas canvas) { - bounds.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + if (wrapContentDynamic) { + float w = text.getCurrentWidth() + getPaddingLeft() + getPaddingRight(); + bounds.set((getMeasuredWidth() - w) / 2f, 0, (getMeasuredWidth() + w) / 2f, getMeasuredHeight()); + } else { + bounds.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + } super.onDraw(canvas); } @@ -69,7 +90,9 @@ public class StickerCutOutBtn extends ButtonWithCounterView { SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_magic_cut); coloredImageSpan.setSize(dp(22)); - coloredImageSpan.setTranslateX(dp(-2)); + coloredImageSpan.setTranslateX(dp(1)); + coloredImageSpan.setTranslateY(dp(2)); + coloredImageSpan.spaceScaleX = 1.2f; cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationCutObject)); setText(cutOutBtnText, animated); @@ -77,12 +100,49 @@ public class StickerCutOutBtn extends ButtonWithCounterView { public void setUndoCutState(boolean animated) { state = STATE_UNDO_CAT; + } + + public void setUndoState(boolean animated) { + state = STATE_UNDO; SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.photo_undo2); coloredImageSpan.setSize(dp(20)); coloredImageSpan.setTranslateX(dp(-3)); cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); - cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationUndoCutOut)); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationUndo)); + setText(cutOutBtnText, animated); + } + + public void setOutlineState(boolean animated) { + state = STATE_OUTLINE; + SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_sticker_stroke); + coloredImageSpan.setSize(dp(20)); + coloredImageSpan.setTranslateX(dp(-3)); + cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationOutline)); + setText(cutOutBtnText, animated); + } + + public void setRestoreState(boolean animated) { + state = STATE_RESTORE; + SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_button_restore); + coloredImageSpan.setSize(dp(20)); + coloredImageSpan.setTranslateX(dp(-3)); + cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationRestore)); + setText(cutOutBtnText, animated); + } + + public void setEraseState(boolean animated) { + state = STATE_ERASE; + SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_button_erase); + coloredImageSpan.setSize(dp(20)); + coloredImageSpan.setTranslateX(dp(-3)); + cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationErase)); setText(cutOutBtnText, animated); } @@ -99,6 +159,10 @@ public class StickerCutOutBtn extends ButtonWithCounterView { return state == STATE_CANCEL; } + public boolean isUndoCutState() { + return state == STATE_UNDO_CAT; + } + public void clean() { setCutOutState(false); } @@ -106,4 +170,17 @@ public class StickerCutOutBtn extends ButtonWithCounterView { public void invalidateBlur() { invalidate(); } + + private boolean wrapContent; + public void wrapContent() { + wrapContent = true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (wrapContent) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec(getPaddingLeft() + (int) text.getCurrentWidth() + getPaddingRight(), MeasureSpec.EXACTLY); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java index 259951f5b..bf7896503 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java @@ -1,6 +1,7 @@ package org.telegram.ui.Components.Paint.Views; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.lerp; import android.animation.ValueAnimator; import android.annotation.SuppressLint; @@ -21,6 +22,8 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; +import android.text.TextUtils; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -34,12 +37,17 @@ import androidx.annotation.Nullable; import com.google.mlkit.common.MlKitException; import com.google.mlkit.vision.common.InputImage; +import com.google.mlkit.vision.label.ImageLabeling; +import com.google.mlkit.vision.label.defaults.ImageLabelerOptions; import com.google.mlkit.vision.segmentation.subject.Subject; import com.google.mlkit.vision.segmentation.subject.SubjectSegmentation; import com.google.mlkit.vision.segmentation.subject.SubjectSegmenter; import com.google.mlkit.vision.segmentation.subject.SubjectSegmenterOptions; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.EmuDetector; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; @@ -49,6 +57,7 @@ import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; @@ -60,10 +69,13 @@ import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Paint.ObjectDetectionEmojis; import org.telegram.ui.Components.ThanosEffect; import org.telegram.ui.Stories.DarkThemeResourceProvider; +import org.telegram.ui.Stories.recorder.DownloadButton; import org.telegram.ui.Stories.recorder.StoryEntry; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -75,6 +87,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. public int currentAccount = -1; private final AnimatedFloat segmentBorderAlpha = new AnimatedFloat(0, (View) null, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat outlineAlpha = new AnimatedFloat(0, (View) null, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); private final Paint dashPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -87,8 +100,11 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. private volatile boolean segmentingLoading; private volatile boolean segmentingLoaded; private SegmentedObject selectedObject; + public float outlineWidth = 2f; + public boolean empty; public SegmentedObject[] objects; private volatile Bitmap sourceBitmap; + public int orientation; private Bitmap filteredBitmap; private boolean isSegmentedState; private final TextView actionTextView; @@ -105,10 +121,15 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. private AlertDialog loadingDialog; private final Theme.ResourcesProvider resourcesProvider; private StickerCutOutBtn stickerCutOutBtn; + public String detectedEmoji; + + private DownloadButton.PreparingVideoToast loadingToast; private final Matrix imageReceiverMatrix = new Matrix(); private float imageReceiverWidth, imageReceiverHeight; + public PaintWeightChooserView weightChooserView; + public StickerMakerView(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; @@ -121,7 +142,6 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. dashPaint.setAlpha(140); actionTextView = new TextView(context); - actionTextView.setText(LocaleController.getString(R.string.SegmentationTabToCrop)); actionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); actionTextView.setTextColor(Color.WHITE); actionTextView.setAlpha(0f); @@ -133,18 +153,37 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. borderPaint.setStrokeWidth(dp(3)); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeCap(Paint.Cap.ROUND); - borderPaint.setPathEffect(new CornerPathEffect(dp(6))); + borderPaint.setPathEffect(new CornerPathEffect(dp(20))); borderPaint.setMaskFilter(new BlurMaskFilter(dp(4), BlurMaskFilter.Blur.NORMAL)); segmentBorderPaint.setColor(Color.WHITE); segmentBorderPaint.setStrokeWidth(dp(3)); segmentBorderPaint.setStyle(Paint.Style.STROKE); segmentBorderPaint.setStrokeCap(Paint.Cap.ROUND); - segmentBorderPaint.setPathEffect(new CornerPathEffect(dp(6))); + segmentBorderPaint.setPathEffect(new CornerPathEffect(dp(20))); segmentBorderPaint.setMaskFilter(new BlurMaskFilter(dp(4), BlurMaskFilter.Blur.NORMAL)); bgPaint.setColor(0x66000000); setLayerType(LAYER_TYPE_HARDWARE, null); + + weightChooserView = new PaintWeightChooserView(context); + weightChooserView.setAlpha(0f); + weightChooserView.setTranslationX(-dp(18)); + weightChooserView.setMinMax(.33f, 10); + weightChooserView.setBrushWeight(outlineWidth); + weightChooserView.setValueOverride(new PaintWeightChooserView.ValueOverride() { + @Override + public float get() { + return outlineWidth; + } + @Override + public void set(float val) { + setOutlineWidth(val); + } + }); + weightChooserView.setTranslationX(-dp(18)); + weightChooserView.setAlpha(0f); + addView(weightChooserView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } public void setStickerCutOutBtn(StickerCutOutBtn stickerCutOutBtn) { @@ -182,7 +221,33 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. public int orientation; public Bitmap image; + public Bitmap overrideImage; public Bitmap darkMaskImage; + public Bitmap overrideDarkMaskImage; + + public Bitmap getImage() { + if (overrideImage != null) { + return overrideImage; + } + return image; + } + + public Bitmap getDarkMaskImage() { + if (overrideDarkMaskImage != null) { + return overrideDarkMaskImage; + } + return darkMaskImage; + } + + public Bitmap makeDarkMaskImage() { + Bitmap darkMaskImage = Bitmap.createBitmap(getImage().getWidth(), getImage().getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(darkMaskImage); + canvas.drawColor(Color.BLACK); + Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + canvas.drawBitmap(getImage(), 0, 0, maskPaint); + return darkMaskImage; + } public RectF bounds = new RectF(); public RectF rotatedBounds = new RectF(); @@ -193,11 +258,78 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. private final Path segmentBorderPath = new Path(); private final Path partSegmentBorderPath = new Path(); - public void drawBorders(Canvas canvas, float progress, float alpha, View parent) { - select.setParent(parent); - if (sourceBitmap == null) return; + private int pointsCount; + private float[] points; + private final Paint bordersFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint bordersStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint bordersDiffStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint pointsPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint pointsHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - final float s = AndroidUtilities.lerp(1f, 1.065f, alpha) * AndroidUtilities.lerp(1f, 1.05f, select.set(hover)); + private final boolean USE_POINTS = true; + public void initPoints() { + PathMeasure pathMeasure = new PathMeasure(); + pathMeasure.setPath(segmentBorderPath, true); + final float length = pathMeasure.getLength(); + final float pointRadius = dp(2); + pointsCount = (int) Math.ceil(length / pointRadius); + this.points = new float[pointsCount * 2]; + final float[] pos = new float[2]; + for (int i = 0; i < pointsCount; ++i) { + pathMeasure.getPosTan(((float) i / pointsCount * length) % length, pos, null); + this.points[i * 2] = pos[0]; + this.points[i * 2 + 1] = pos[1]; + } + + bordersFillPaint.setStyle(Paint.Style.FILL); + bordersFillPaint.setColor(Color.WHITE); + bordersFillPaint.setStrokeJoin(Paint.Join.ROUND); + bordersFillPaint.setStrokeCap(Paint.Cap.ROUND); + bordersFillPaint.setPathEffect(new CornerPathEffect(dp(10))); + bordersStrokePaint.setStyle(Paint.Style.STROKE); + bordersStrokePaint.setColor(Color.WHITE); + bordersStrokePaint.setStrokeJoin(Paint.Join.ROUND); + bordersStrokePaint.setStrokeCap(Paint.Cap.ROUND); + bordersStrokePaint.setPathEffect(new CornerPathEffect(dp(10))); + + pointsPaint.setStyle(Paint.Style.STROKE); + pointsPaint.setStrokeWidth(dp(4)); + pointsPaint.setColor(0xFFFFFFFF); + pointsPaint.setStrokeCap(Paint.Cap.ROUND); + pointsPaint.setMaskFilter(new BlurMaskFilter(dp(.33f), BlurMaskFilter.Blur.NORMAL)); + + pointsHighlightPaint.setStyle(Paint.Style.STROKE); + pointsHighlightPaint.setColor(Theme.multAlpha(0xFFFFFFFF, .04f)); + pointsHighlightPaint.setStrokeCap(Paint.Cap.ROUND); + pointsHighlightPaint.setStrokeWidth(dp(20)); + pointsHighlightPaint.setColor(Theme.multAlpha(Color.WHITE, .04f)); + pointsHighlightPaint.setMaskFilter(new BlurMaskFilter(dp(60), BlurMaskFilter.Blur.NORMAL)); + } + + public void drawOutline(Canvas canvas, boolean after, float width, float alpha) { + if (outlineBoundsPath == null) + return; + canvas.save(); + canvas.clipPath(outlineBoundsPath); + if (sourceBitmap != null) { + Paint paint = after ? bordersStrokePaint : bordersFillPaint; + paint.setAlpha((int) (0xFF * alpha)); + paint.setStrokeWidth(dp(width)); + canvas.drawPath(segmentBorderPath, paint); + if (outlineBoundsPath != null && after) { + canvas.clipPath(segmentBorderPath); + paint.setStrokeWidth(dp(2 * width)); + canvas.drawPath(outlineBoundsPath, paint); + } + } + canvas.restore(); + } + + public void drawAnimationBorders(Canvas canvas, float progress, float alpha, View parent) { + select.setParent(parent); + if (sourceBitmap == null || alpha <= 0) return; + + final float s = lerp(1f, 1.065f, alpha) * lerp(1f, 1.05f, select.set(hover)); int w, h; if (orientation / 90 % 2 != 0) { @@ -211,50 +343,87 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. canvas.save(); canvas.scale(s, s, rotatedBounds.centerX() / w * borderImageWidth - borderImageWidth / 2f, rotatedBounds.centerY() / h * borderImageHeight - borderImageHeight / 2f); - bordersPathMeasure.setPath(segmentBorderPath, false); - partSegmentBorderPath.reset(); - - float length = bordersPathMeasure.getLength(); - if (length == 0) { - return; + if (USE_POINTS && points != null) { + final int fromIndex = (int) (progress * pointsCount); + final int toIndex = fromIndex + Math.min(500, (int) (.6f * pointsCount)); + if (pointsCount > 0) { + for (int i = fromIndex; i <= toIndex; ++i) { + final float ha = (1f - (toIndex - i) / (float) pointsCount); + if (ha > 0) { + pointsHighlightPaint.setAlpha((int) (0xFF * .04f * ha * alpha)); + canvas.drawPoints(points, (i % pointsCount) * 2, 2, pointsHighlightPaint); + } + } + } } - segmentBorderPaint.setAlpha((int) (0xFF * alpha)); - borderPaint.setAlpha((int) (0x40 * alpha)); - canvas.drawPath(partSegmentBorderPath, borderPaint); - - float toPercent = progress + 0.2f; - float from = length * progress; - float to = length * toPercent; - bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); - canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); - canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); - if (toPercent > 1) { - from = 0; - to = (toPercent - 1) * length; - partSegmentBorderPath.reset(); - bordersPathMeasure.setPath(segmentBorderPath, false); - bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); - canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); - canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); - } - - if (image != null) { + if (getImage() != null) { canvas.save(); canvas.rotate(orientation); canvas.scale(1f / w * borderImageWidth, 1f / h * borderImageHeight); - canvas.drawBitmap(image, -sourceBitmap.getWidth() / 2f, -sourceBitmap.getHeight() / 2f, null); + canvas.drawBitmap(getImage(), -sourceBitmap.getWidth() / 2f, -sourceBitmap.getHeight() / 2f, null); canvas.restore(); } + + if (USE_POINTS && points != null) { + final int fromIndex = (int) (progress * pointsCount); + final int toIndex = fromIndex + Math.min(500, (int) (.6f * pointsCount)); + if (pointsCount > 0) { + for (int i = fromIndex; i <= toIndex; ++i) { + final float p = (float) (i - fromIndex) / (toIndex - fromIndex); + final float a = Math.min(1, 4f * Math.min(p, 1 - p)); + pointsPaint.setAlpha((int) (0xFF * a * alpha)); + canvas.drawPoints(points, (i % pointsCount) * 2, 2, pointsPaint); + } + } + } else { + bordersPathMeasure.setPath(segmentBorderPath, false); + partSegmentBorderPath.reset(); + + float length = bordersPathMeasure.getLength(); + if (length == 0) { + return; + } + + segmentBorderPaint.setAlpha((int) (0xFF * alpha)); + borderPaint.setAlpha((int) (0x40 * alpha)); + canvas.drawPath(partSegmentBorderPath, borderPaint); + + float toPercent = progress + 0.2f; + float from = length * progress; + float to = length * toPercent; + bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); + + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + if (toPercent > 1) { + from = 0; + to = (toPercent - 1) * length; + partSegmentBorderPath.reset(); + bordersPathMeasure.setPath(segmentBorderPath, false); + bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + } + } + canvas.restore(); } public void recycle() { segmentBorderPath.reset(); + if (overrideImage != null) { + overrideImage.recycle(); + overrideImage = null; + } if (image != null) { image.recycle(); image = null; } + if (overrideDarkMaskImage != null) { + overrideDarkMaskImage.recycle(); + overrideDarkMaskImage = null; + } if (darkMaskImage != null) { darkMaskImage.recycle(); darkMaskImage = null; @@ -262,24 +431,123 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. } } + public void setOutlineWidth(float width) { + outlineWidth = width; + if (getParent() instanceof View) { + ((View) getParent()).invalidate(); + } + } + + public void updateOutlinePath(Bitmap newMaskBitmap) { + if (selectedObject == null) return; + selectedObject.overrideImage = createSmoothEdgesSegmentedImage(0, 0, newMaskBitmap, true); + selectedObject.overrideDarkMaskImage = selectedObject.makeDarkMaskImage(); + createSegmentImagePath(selectedObject, containerWidth, containerHeight); + } + + public boolean overriddenPaths() { + if (objects != null) { + for (SegmentedObject obj : objects) { + if (obj != null && obj.overrideImage != null) { + return true; + } + } + } + return false; + } + + public void resetPaths() { + if (objects != null) { + for (SegmentedObject obj : objects) { + if (obj != null && obj.overrideImage != null) { + obj.overrideImage.recycle(); + obj.overrideImage = null; + if (obj.overrideDarkMaskImage != null) { + obj.overrideDarkMaskImage.recycle(); + obj.overrideDarkMaskImage = null; + } + createSegmentImagePath(obj, containerWidth, containerHeight); + } + } + } + } + + public boolean outlineVisible; + public void setOutlineVisible(boolean visible) { + if (outlineVisible == visible) return; + outlineVisible = visible; + weightChooserView.animate().alpha(visible ? 1f : 0f).translationX(visible ? 0 : dp(-18)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + if (getParent() instanceof View) { + ((View) getParent()).invalidate(); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + exclusionRects.clear(); + if (outlineVisible) { + exclusionRects.add(exclusionRect); + int h = (int) (getMeasuredHeight() * .3f); + exclusionRect.set(0, (getMeasuredHeight() - h) / 2, dp(20), (getMeasuredHeight() + h) / 2); + } + setSystemGestureExclusionRects(exclusionRects); + } + } + + public void drawOutline(Canvas canvas, boolean after, ViewGroup parent, boolean hide) { + this.outlineAlpha.setParent(parent); + if (!outlineVisible && this.outlineAlpha.get() <= 0) { + return; + } + + final float outlineAlpha = parent == null ? 1f : this.outlineAlpha.set(outlineVisible && !hide); + if (objects != null) { + for (SegmentedObject object : objects) { + if (object != null && object == selectedObject && outlineWidth > 0) { + object.drawOutline(canvas, after, outlineWidth, outlineAlpha); + break; + } + } + } + } + + public boolean setOutlineBounds; + public final Matrix outlineMatrix = new Matrix(); + private Path outlineBoundsPath, outlineBoundsInnerPath; + private final RectF outlineBounds = new RectF(); + public void updateOutlineBounds(boolean set) { + setOutlineBounds = set; + if (set) { + if (outlineBoundsPath == null) { + outlineBoundsPath = new Path(); + } else { + outlineBoundsPath.rewind(); + } + if (outlineBoundsInnerPath == null) { + outlineBoundsInnerPath = new Path(); + AndroidUtilities.rectTmp.set(0, 0, 1, 1); + outlineBoundsInnerPath.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.rectTmp.width() * .12f, AndroidUtilities.rectTmp.height() * .12f, Path.Direction.CW); + } + outlineBoundsPath.addPath(outlineBoundsInnerPath, outlineMatrix); + outlineBoundsPath.computeBounds(outlineBounds, true); + } + } public void drawSegmentBorderPath(Canvas canvas, ImageReceiver imageReceiver, Matrix matrix, ViewGroup parent) { segmentBorderAlpha.setParent(parent); - if ((bordersAnimator == null && segmentBorderAlpha.get() <= 0) || parent == null) { + if (bordersAnimator == null && segmentBorderAlpha.get() <= 0 || parent == null) { return; } imageReceiverWidth = imageReceiver.getImageWidth(); imageReceiverHeight = imageReceiver.getImageHeight(); - matrix.invert(imageReceiverMatrix); + imageReceiverMatrix.set(matrix); float progress = (bordersAnimatorValueStart + bordersAnimatorValue) % 1.0f; - float alpha = segmentBorderAlpha.set(bordersAnimator == null ? 0f : 1f); + float alpha = segmentBorderAlpha.set(bordersAnimator != null); canvas.drawColor(Theme.multAlpha(0x50000000, alpha)); if (objects != null) { for (SegmentedObject object : objects) { - object.drawBorders(canvas, progress, alpha, parent); + if (object == null) continue; + object.drawAnimationBorders(canvas, progress, alpha, parent); } } @@ -298,6 +566,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. } }); + actionTextView.setText(LocaleController.getString(R.string.SegmentationTabToCrop)); actionTextView.animate().cancel(); actionTextView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(240).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); if (bordersAnimator != null) { @@ -337,26 +606,27 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. } public SegmentedObject objectBehind(float tx, float ty) { - float[] p = new float[] { tx, ty }; - imageReceiverMatrix.mapPoints(p); - int w, h; - if (objects[0].orientation / 90 % 2 != 0) { - w = sourceBitmap.getHeight(); - h = sourceBitmap.getWidth(); - } else { - w = sourceBitmap.getWidth(); - h = sourceBitmap.getHeight(); - } + if (sourceBitmap == null) return null; for (int i = 0; i < objects.length; ++i) { + SegmentedObject obj = objects[i]; + if (obj == null) continue; + int w, h; + if (objects[i].orientation / 90 % 2 != 0) { + w = sourceBitmap.getHeight(); + h = sourceBitmap.getWidth(); + } else { + w = sourceBitmap.getWidth(); + h = sourceBitmap.getHeight(); + } AndroidUtilities.rectTmp.set( objects[i].rotatedBounds.left / w * imageReceiverWidth, objects[i].rotatedBounds.top / h * imageReceiverHeight, objects[i].rotatedBounds.right / w * imageReceiverWidth, objects[i].rotatedBounds.bottom / h * imageReceiverHeight ); - AndroidUtilities.rectTmp.offset(-imageReceiverWidth / 2f, -imageReceiverHeight / 2f); - if (AndroidUtilities.rectTmp.contains(p[0], p[1])) { - return objects[i]; + imageReceiverMatrix.mapRect(AndroidUtilities.rectTmp); + if (AndroidUtilities.rectTmp.contains(tx, ty)) { + return obj; } } return null; @@ -374,10 +644,22 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. actionTextView.animate().alpha(0f).scaleX(0.7f).scaleY(0.7f).setDuration(240).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); } + private ArrayList exclusionRects = new ArrayList<>(); + private Rect exclusionRect = new Rect(); + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - actionTextView.setTranslationY(getMeasuredWidth() / 2f + dp(10)); + actionTextView.setTranslationY(-(getMeasuredWidth() / 2f + dp(10))); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + exclusionRects.clear(); + if (outlineVisible) { + exclusionRects.add(exclusionRect); + int h = (int) (getMeasuredHeight() * .3f); + exclusionRect.set(0, (getMeasuredHeight() - h) / 2, dp(20), (getMeasuredHeight() + h) / 2); + } + setSystemGestureExclusionRects(exclusionRects); + } } public boolean isSegmentedState() { @@ -390,7 +672,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. } public Bitmap getSegmentedDarkMaskImage() { - return isSegmentedState && selectedObject != null ? selectedObject.darkMaskImage : null; + return isSegmentedState && selectedObject != null ? selectedObject.getDarkMaskImage() : null; } public boolean hasSegmentedBitmap() { @@ -415,7 +697,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. if (hasFilters && filteredBitmap != null) { return cutSegmentInFilteredBitmap(filteredBitmap, orientation); } - return selectedObject.image; + return selectedObject.getImage(); } @Nullable @@ -442,15 +724,15 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. if (object.orientation != 0 && photoEntry.isFiltered) { Matrix matrix = new Matrix(); - matrix.postRotate(object.orientation, object.darkMaskImage.getWidth() / 2f, object.darkMaskImage.getHeight() / 2f); + matrix.postRotate(object.orientation, object.getDarkMaskImage().getWidth() / 2f, object.getDarkMaskImage().getHeight() / 2f); if (object.orientation / 90 % 2 != 0) { - float dxy = (object.darkMaskImage.getHeight() - object.darkMaskImage.getWidth()) / 2f; + float dxy = (object.getDarkMaskImage().getHeight() - object.getDarkMaskImage().getWidth()) / 2f; matrix.postTranslate(dxy, -dxy); } - matrix.postScale(filteredBitmap.getWidth() / (float) object.darkMaskImage.getHeight(), filteredBitmap.getHeight() / (float) object.darkMaskImage.getWidth()); - canvas.drawBitmap(object.darkMaskImage, matrix, maskPaint); + matrix.postScale(filteredBitmap.getWidth() / (float) object.getDarkMaskImage().getHeight(), filteredBitmap.getHeight() / (float) object.getDarkMaskImage().getWidth()); + canvas.drawBitmap(object.getDarkMaskImage(), matrix, maskPaint); } else { - canvas.drawBitmap(object.darkMaskImage, null, dstRect, maskPaint); + canvas.drawBitmap(object.getDarkMaskImage(), null, dstRect, maskPaint); } if (paintedBitmap != null) { @@ -502,15 +784,20 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. canvas.drawPath(dashPath, dashPaint); } - private Bitmap createSmoothEdgesSegmentedImage(int x, int y, Bitmap inputBitmap) { + private Bitmap createSmoothEdgesSegmentedImage(int x, int y, Bitmap inputBitmap, boolean full) { Bitmap srcBitmap = getSourceBitmap(); - if (inputBitmap == null || srcBitmap == null) { + if (inputBitmap == null || inputBitmap.isRecycled() || srcBitmap == null) { return null; } Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); Bitmap bluredBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bluredBitmap); - canvas.drawBitmap(inputBitmap, x, y, bitmapPaint); + if (full) { + canvas.scale((float) bluredBitmap.getWidth() / inputBitmap.getWidth(), (float) bluredBitmap.getHeight() / inputBitmap.getHeight()); + canvas.drawBitmap(inputBitmap, x, y, bitmapPaint); + } else { + canvas.drawBitmap(inputBitmap, x, y, bitmapPaint); + } Utilities.stackBlurBitmap(bluredBitmap, 5); Bitmap resultBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888); @@ -524,7 +811,13 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. return segmentedImage; } - public void segmentImage(Bitmap source, int orientation, int containerWidth, int containerHeight) { + public void segmentImage(Bitmap source, int orientation, int containerWidth, int containerHeight, Utilities.Callback whenEmpty) { + if (containerWidth <= 0) { + containerWidth = AndroidUtilities.displaySize.x; + } + if (containerHeight <= 0) { + containerHeight = AndroidUtilities.displaySize.y; + } this.containerWidth = containerWidth; this.containerHeight = containerHeight; if (segmentingLoaded) { @@ -532,6 +825,112 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. } if (segmentingLoading || source == null) return; if (Build.VERSION.SDK_INT < 24) return; + sourceBitmap = source; + this.orientation = orientation; + detectedEmoji = null; + segment(source, orientation, subjects -> { + final ArrayList finalObjects = new ArrayList<>(); + + Utilities.themeQueue.postRunnable(() -> { + if (sourceBitmap == null || segmentingLoaded) return; + Matrix matrix = new Matrix(); + matrix.postScale(1f / sourceBitmap.getWidth(), 1f / sourceBitmap.getHeight()); + matrix.postTranslate(-.5f, -.5f); + matrix.postRotate(orientation); + matrix.postTranslate(.5f, .5f); + if (orientation / 90 % 2 != 0) { + matrix.postScale(sourceBitmap.getHeight(), sourceBitmap.getWidth()); + } else { + matrix.postScale(sourceBitmap.getWidth(), sourceBitmap.getHeight()); + } + if (subjects.isEmpty()) { + SegmentedObject o = new SegmentedObject(); + o.bounds.set(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()); + o.rotatedBounds.set(o.bounds); + matrix.mapRect(o.rotatedBounds); + o.orientation = orientation; + o.image = createSmoothEdgesSegmentedImage(0, 0, sourceBitmap, false); + if (o.image == null) { + FileLog.e(new RuntimeException("createSmoothEdgesSegmentedImage failed on empty image")); + return; + } + o.darkMaskImage = o.makeDarkMaskImage(); + createSegmentImagePath(o, this.containerWidth, this.containerHeight); + segmentBorderImageWidth = o.borderImageWidth; + segmentBorderImageHeight = o.borderImageHeight; + + finalObjects.add(o); + AndroidUtilities.runOnUIThread(() -> { + empty = true; + objects = finalObjects.toArray(new SegmentedObject[0]); + whenEmpty.run(o); + }); + selectedObject = o; + segmentingLoaded = true; + segmentingLoading = false; + return; + } else { + for (int i = 0; i < subjects.size(); ++i) { + SubjectMock subject = subjects.get(i); + SegmentedObject o = new SegmentedObject(); + o.bounds.set(subject.startX, subject.startY, subject.startX + subject.width, subject.startY + subject.height); + o.rotatedBounds.set(o.bounds); + matrix.mapRect(o.rotatedBounds); + o.orientation = orientation; + o.image = createSmoothEdgesSegmentedImage(subject.startX, subject.startY, subject.bitmap, false); + if (o.image == null) continue; + o.darkMaskImage = o.makeDarkMaskImage(); + createSegmentImagePath(o, this.containerWidth, this.containerHeight); + segmentBorderImageWidth = o.borderImageWidth; + segmentBorderImageHeight = o.borderImageHeight; + + finalObjects.add(o); + } + } + selectedObject = null; + + segmentingLoaded = true; + segmentingLoading = false; + AndroidUtilities.runOnUIThread(() -> { + empty = false; + objects = finalObjects.toArray(new SegmentedObject[0]); + if (objects.length > 0) { + stickerCutOutBtn.setScaleX(0.3f); + stickerCutOutBtn.setScaleY(0.3f); + stickerCutOutBtn.setAlpha(0f); + stickerCutOutBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(250).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); + } + }); + + }); + }, whenEmpty); + } + + private static class SubjectMock { + public Bitmap bitmap; + public int startX, startY, width, height; + public static SubjectMock of(Subject subject) { + SubjectMock m = new SubjectMock(); + m.bitmap = subject.getBitmap(); + m.startX = subject.getStartX(); + m.startY = subject.getStartY(); + m.width = subject.getWidth(); + m.height = subject.getHeight(); + return m; + } + public static SubjectMock mock(Bitmap source) { + SubjectMock m = new SubjectMock(); + m.width = m.height = (int) (Math.min(source.getWidth(), source.getHeight()) * .4f); + m.bitmap = Bitmap.createBitmap(m.width, m.height, Bitmap.Config.ARGB_8888); + new Canvas(m.bitmap).drawRect(0, 0, m.width, m.height, Theme.DEBUG_RED); + m.startX = (source.getWidth() - m.width) / 2; + m.startY = (source.getHeight() - m.height) / 2; + return m; + } + } + + private void segment(Bitmap bitmap, int orientation, Utilities.Callback> whenDone, Utilities.Callback whenEmpty) { + segmentingLoading = true; SubjectSegmenter segmenter = SubjectSegmentation.getClient( new SubjectSegmenterOptions.Builder() .enableMultipleSubjects( @@ -541,85 +940,64 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. ) .build() ); - segmentingLoading = true; - sourceBitmap = source; - InputImage inputImage = InputImage.fromBitmap(source, orientation); + if (EmuDetector.with(getContext()).detect()) { + ArrayList list = new ArrayList<>(); + list.add(SubjectMock.mock(sourceBitmap)); + whenDone.run(list); + return; + } + InputImage inputImage = InputImage.fromBitmap(bitmap, orientation); segmenter.process(inputImage) - .addOnSuccessListener(result -> { - if (sourceBitmap == null) return; - final ArrayList finalObjects = new ArrayList<>(); - Utilities.themeQueue.postRunnable(() -> { - if (sourceBitmap == null) return; - List subjects = result.getSubjects(); - Matrix matrix = new Matrix(); - matrix.postScale(1f / sourceBitmap.getWidth(), 1f / sourceBitmap.getHeight()); - matrix.postTranslate(-.5f, -.5f); - matrix.postRotate(orientation); - matrix.postTranslate(.5f, .5f); - if (orientation / 90 % 2 != 0) { - matrix.postScale(sourceBitmap.getHeight(), sourceBitmap.getWidth()); - } else { - matrix.postScale(sourceBitmap.getWidth(), sourceBitmap.getHeight()); - } - for (int i = 0; i < subjects.size(); ++i) { - Subject subject = subjects.get(i); - SegmentedObject o = new SegmentedObject(); - o.bounds.set(subject.getStartX(), subject.getStartY(), subject.getStartX() + subject.getWidth(), subject.getStartY() + subject.getHeight()); - o.rotatedBounds.set(o.bounds); - matrix.mapRect(o.rotatedBounds); - o.orientation = orientation; - o.image = createSmoothEdgesSegmentedImage(subject.getStartX(), subject.getStartY(), subject.getBitmap()); - if (o.image == null) continue; + .addOnSuccessListener(result -> { + ArrayList list = new ArrayList<>(); + for (int i = 0; i < result.getSubjects().size(); ++i) { + list.add(SubjectMock.of(result.getSubjects().get(i))); + } + whenDone.run(list); + }) + .addOnFailureListener(error -> { + segmentingLoading = false; + FileLog.e(error); + if (isWaitingMlKitError(error) && isAttachedToWindow()) { + AndroidUtilities.runOnUIThread(() -> segmentImage(bitmap, orientation, containerWidth, containerHeight, whenEmpty), 2000); + } else { + whenDone.run(new ArrayList<>()); + } + }); - o.darkMaskImage = Bitmap.createBitmap(o.image.getWidth(), o.image.getHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(o.darkMaskImage); - canvas.drawColor(Color.BLACK); - Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); - maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - canvas.drawBitmap(o.image, 0, 0, maskPaint); - createSegmentImagePath(o, containerWidth, containerHeight); - segmentBorderImageWidth = o.borderImageWidth; - segmentBorderImageHeight = o.borderImageHeight; - - finalObjects.add(o); - } - selectedObject = null; - - segmentingLoaded = true; - segmentingLoading = false; - AndroidUtilities.runOnUIThread(() -> { - objects = finalObjects.toArray(new SegmentedObject[1]); - if (objects.length > 0) { - stickerCutOutBtn.setScaleX(0.3f); - stickerCutOutBtn.setScaleY(0.3f); - stickerCutOutBtn.setAlpha(0f); - stickerCutOutBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(250).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); - } - }); - - }); - }) - .addOnFailureListener(error -> { - segmentingLoading = false; - FileLog.e(error); - if (isWaitingMlKitError(error) && isAttachedToWindow()) { - AndroidUtilities.runOnUIThread(() -> segmentImage(source, orientation, containerWidth, containerHeight), 2000); - } else { - segmentingLoaded = true; + if (detectedEmoji == null) { + ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS) + .process(inputImage) + .addOnSuccessListener(labels -> { + if (labels.size() <= 0) { + FileLog.d("objimg: no objects"); + return; } + detectedEmoji = ObjectDetectionEmojis.labelToEmoji(labels.get(0).getIndex()); + FileLog.d("objimg: detected #" + labels.get(0).getIndex() + " " + detectedEmoji + " " + labels.get(0).getText()); + Emoji.getEmojiDrawable(detectedEmoji); // preload + }) + .addOnFailureListener(e -> { }); + } + + // preload emojis + List defaultReactions = MediaDataController.getInstance(currentAccount).getEnabledReactionsList(); + for (int i = 0; i <= Math.min(defaultReactions.size(), 8); ++i) { + Emoji.getEmojiDrawable(defaultReactions.get(i).reaction); + } } private void createSegmentImagePath(SegmentedObject object, int containerWidth, int containerHeight) { - int imageWidth = object.image.getWidth(); - int imageHeight = object.image.getHeight(); + int imageWidth = object.getImage().getWidth(); + int imageHeight = object.getImage().getHeight(); int maxImageSize = Math.max(imageWidth, imageHeight); - float scaleFactor = maxImageSize / 256f; + float scaleFactor = maxImageSize / (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH ? 512f : 384f); if (object.orientation / 90 % 2 != 0) { - imageWidth = object.image.getHeight(); - imageHeight = object.image.getWidth(); + imageWidth = object.getImage().getHeight(); + imageHeight = object.getImage().getWidth(); } Bitmap bitmap = Bitmap.createBitmap((int) (imageWidth / scaleFactor), (int) (imageHeight / scaleFactor), Bitmap.Config.ARGB_8888); @@ -628,15 +1006,15 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. rectF.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); if (object.orientation != 0) { Matrix matrix = new Matrix(); - matrix.postRotate(object.orientation, object.image.getWidth() / 2f, object.image.getHeight() / 2f); + matrix.postRotate(object.orientation, object.getImage().getWidth() / 2f, object.image.getHeight() / 2f); if (object.orientation / 90 % 2 != 0) { - float dxy = (object.image.getHeight() - object.image.getWidth()) / 2f; + float dxy = (object.getImage().getHeight() - object.getImage().getWidth()) / 2f; matrix.postTranslate(dxy, -dxy); } matrix.postScale(rectF.width() / imageWidth, rectF.height() / imageHeight); - canvas.drawBitmap(object.image, matrix, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawBitmap(object.getImage(), matrix, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); } else { - canvas.drawBitmap(object.image, null, rectF, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawBitmap(object.getImage(), null, rectF, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); } int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()]; @@ -647,7 +1025,10 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. Point leftPoint = null; Point rightPoint = null; - scaleFactor = containerWidth / (float) bitmap.getWidth(); + scaleFactor = Math.min( + containerWidth / (float) bitmap.getWidth(), + containerHeight / (float) bitmap.getHeight() + ); for (int i = 0; i < pixels.length; i++) { int y = i / bitmap.getWidth(); int x = i - y * bitmap.getWidth(); @@ -730,8 +1111,8 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. topBottomPointsSet.addAll(bottomPoints); topBottomPointsSet.addAll(topPoints); - List topBottomPointsList = new ArrayList<>(topBottomPointsSet); - List leftRightPointsList = new ArrayList<>(leftRightPointsSet); + List topBottomPointsList = removeUnnecessaryPoints(new ArrayList<>(topBottomPointsSet)); + List leftRightPointsList = removeUnnecessaryPoints(new ArrayList<>(leftRightPointsSet)); Path path1 = new Path(); for (int i = 0; i < leftRightPointsList.size(); i += 2) { @@ -762,9 +1143,38 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. object.borderImageWidth = imageWidth * scaleFactor; object.borderImageHeight = imageHeight * scaleFactor; object.segmentBorderPath.offset(-object.borderImageWidth / 2f, -object.borderImageHeight / 2f); + object.initPoints(); + } + + public static List removeUnnecessaryPoints(List points) { + if (points.size() < 3) return points; + + List optimizedPoints = new ArrayList<>(); + optimizedPoints.add(points.get(0)); + + for (int i = 1; i < points.size() - 1; i++) { + Point prev = points.get(i - 1); + Point curr = points.get(i); + Point next = points.get(i + 1); + + if (!isPointOnLine(prev, curr, next)) { + optimizedPoints.add(curr); + } + } + + optimizedPoints.add(points.get(points.size() - 1)); + return optimizedPoints; + } + + private static boolean isPointOnLine(Point a, Point b, Point c) { + int crossProduct = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); + return Math.abs(crossProduct - (-1.0f)) < 0.15f; } public Bitmap cutSegmentInFilteredBitmap(Bitmap filteredBitmap, int orientation) { + if (filteredBitmap == null) { + return null; + } if (selectedObject == null) { return filteredBitmap; } @@ -782,15 +1192,15 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. dstRect.set(0, 0, filteredBitmap.getWidth(), filteredBitmap.getHeight()); if (selectedObject.orientation != 0) { Matrix matrix = new Matrix(); - matrix.postRotate(selectedObject.orientation, selectedObject.darkMaskImage.getWidth() / 2f, selectedObject.darkMaskImage.getHeight() / 2f); + matrix.postRotate(selectedObject.orientation, selectedObject.getDarkMaskImage().getWidth() / 2f, selectedObject.getDarkMaskImage().getHeight() / 2f); if (selectedObject.orientation / 90 % 2 != 0) { - float dxy = (selectedObject.image.getHeight() - selectedObject.image.getWidth()) / 2f; + float dxy = (selectedObject.getImage().getHeight() - selectedObject.getImage().getWidth()) / 2f; matrix.postTranslate(dxy, -dxy); } - matrix.postScale(filteredBitmap.getWidth() / (float) selectedObject.darkMaskImage.getHeight(), filteredBitmap.getHeight() / (float) selectedObject.darkMaskImage.getWidth()); - canvas.drawBitmap(selectedObject.darkMaskImage, matrix, maskPaint); + matrix.postScale(filteredBitmap.getWidth() / (float) selectedObject.getDarkMaskImage().getHeight(), filteredBitmap.getHeight() / (float) selectedObject.getDarkMaskImage().getWidth()); + canvas.drawBitmap(selectedObject.getDarkMaskImage(), matrix, maskPaint); } else { - canvas.drawBitmap(selectedObject.darkMaskImage, null, dstRect, maskPaint); + canvas.drawBitmap(selectedObject.getDarkMaskImage(), null, dstRect, maskPaint); } return result; } @@ -815,6 +1225,13 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. actionTextView.setAlpha(0f); actionTextView.setScaleX(0.3f); actionTextView.setScaleY(0.3f); + if (stickerUploader != null) { + if (!stickerUploader.uploaded) + stickerUploader.destroy(true); + stickerUploader = null; + } + hideLoadingDialog(); + isThanosInProgress = false; } public static boolean isWaitingMlKitError(Exception e) { @@ -823,8 +1240,9 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. public void setCurrentAccount(int account) { if (currentAccount != account) { - if (currentAccount >= 0) { + if (currentAccount >= 0 && isAttachedToWindow()) { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingStarted); @@ -833,8 +1251,9 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. currentAccount = account; - if (currentAccount >= 0) { + if (currentAccount >= 0 && isAttachedToWindow()) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingStarted); @@ -848,6 +1267,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. super.onDetachedFromWindow(); if (currentAccount >= 0) { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingStarted); @@ -860,6 +1280,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. super.onAttachedToWindow(); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingStarted); @@ -875,6 +1296,18 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. stickerUploader.file = file; uploadMedia(); } + } else if (id == NotificationCenter.fileUploadProgressChanged) { + String location = (String) args[0]; + if (stickerUploader != null && location.equalsIgnoreCase(stickerUploader.finalPath)) { + final long uploadedSize = (long) args[1]; + final long totalSize = (long) args[2]; + if (totalSize > 0) { + stickerUploader.uploadProgress = Utilities.clamp(uploadedSize / (float) totalSize, 1, stickerUploader.uploadProgress); + if (loadingToast != null) { + loadingToast.setProgress(stickerUploader.getProgress()); + } + } + } } else if (id == NotificationCenter.fileUploadFailed) { String location = (String) args[0]; if (stickerUploader != null && location.equalsIgnoreCase(stickerUploader.finalPath)) { @@ -892,21 +1325,14 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. long availableSize = (Long) args[2]; long finalSize = (Long) args[3]; float convertingProgress = (float) args[4]; -// progress = convertingProgress * .3f + uploadProgress * .7f; -// NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.uploadStoryProgress, path, progress); - -// if (firstSecondSize < 0 && convertingProgress * duration >= 1000) { -// firstSecondSize = availableSize; -// } + stickerUploader.messageObject.videoEditedInfo.needUpdateProgress = true; FileLoader.getInstance(currentAccount).checkUploadNewDataAvailable(finalPath, false, Math.max(1, availableSize), finalSize, convertingProgress); -// if (finalSize > 0) { -// if (firstSecondSize < 0) { -// firstSecondSize = finalSize; -// } -// ready = true; -// } + stickerUploader.convertingProgress = Math.max(stickerUploader.convertingProgress, convertingProgress); + if (loadingToast != null) { + loadingToast.setProgress(stickerUploader.getProgress()); + } } } else if (id == NotificationCenter.filePreparingFailed) { if (stickerUploader == null) return; @@ -916,9 +1342,15 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. } } - public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, String emoji, CharSequence stickerPackName, boolean addToFavorite, TLRPC.StickerSet stickerSet, TLRPC.Document replacedSticker) { + public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, String emoji, CharSequence stickerPackName, boolean addToFavorite, TLRPC.StickerSet stickerSet, TLRPC.Document replacedSticker, String thumbPath, Utilities.Callback whenDone, Utilities.Callback2 customStickerHandler) { AndroidUtilities.runOnUIThread(() -> { - stickerUploader = new StickerUploader(); + final boolean newStickerUploader = !(whenDone != null && stickerUploader != null && stickerUploader.uploaded); + if (newStickerUploader) { + if (stickerUploader != null) { + stickerUploader.destroy(true); + } + stickerUploader = new StickerUploader(); + } stickerUploader.emoji = emoji; stickerUploader.path = stickerUploader.finalPath = path; stickerUploader.stickerPackName = stickerPackName; @@ -926,7 +1358,13 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. stickerUploader.stickerSet = stickerSet; stickerUploader.replacedSticker = replacedSticker; stickerUploader.videoEditedInfo = videoEditedInfo; - if (videoEditedInfo != null) { + stickerUploader.thumbPath = thumbPath; + stickerUploader.whenDone = whenDone; + stickerUploader.customHandler = customStickerHandler; + stickerUploader.setupFiles(); + if (!newStickerUploader) { + afterUploadingMedia(); + } else if (videoEditedInfo != null) { TLRPC.TL_message message = new TLRPC.TL_message(); message.id = 1; stickerUploader.finalPath = message.attachPath = StoryEntry.makeCacheFile(UserConfig.selectedAccount, "webm").getAbsolutePath(); @@ -934,25 +1372,50 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. stickerUploader.messageObject.videoEditedInfo = videoEditedInfo; MediaController.getInstance().scheduleVideoConvert(stickerUploader.messageObject, false, false); } else { - FileLoader.getInstance(UserConfig.selectedAccount).uploadFile(path, false, true, ConnectionsManager.FileTypeFile); + FileLoader.getInstance(currentAccount).uploadFile(path, false, true, ConnectionsManager.FileTypeFile); + } + if (whenDone == null) { + showLoadingDialog(); } - showLoadingDialog(); }, 300); } private void showLoadingDialog() { - loadingDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER, new DarkThemeResourceProvider()); - loadingDialog.show(); + if (loadingToast == null) { + loadingToast = new DownloadButton.PreparingVideoToast(getContext()); + } + loadingToast.setOnCancelListener(() -> { + if (stickerUploader != null) { + if (stickerUploader.messageObject != null) { + MediaController.getInstance().cancelVideoConvert(stickerUploader.messageObject); + FileLoader.getInstance(currentAccount).cancelFileUpload(stickerUploader.finalPath, false); + if (stickerUploader.reqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(stickerUploader.reqId, true); + } + } + stickerUploader.destroy(true); + stickerUploader = null; + } + loadingToast.hide(); + loadingToast = null; + }); + if (loadingToast.getParent() == null) { + addView(loadingToast, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); + } + loadingToast.show(); } private void hideLoadingDialog() { - if (loadingDialog != null) { - loadingDialog.dismiss(); - loadingDialog = null; + if (loadingToast != null) { + loadingToast.hide(); + loadingToast = null; } } private void uploadMedia() { + final StickerUploader stickerUploader = this.stickerUploader; + if (stickerUploader == null) + return; TLRPC.TL_messages_uploadMedia req = new TLRPC.TL_messages_uploadMedia(); req.peer = new TLRPC.TL_inputPeerSelf(); req.media = new TLRPC.TL_inputMediaUploadedDocument(); @@ -981,23 +1444,54 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. private void showError(TLRPC.TL_error error) { if (error != null) { + if ("PACK_TITLE_INVALID".equals(error.text)) { + return; + } BulletinFactory.of((FrameLayout) getParent(), resourcesProvider).createErrorBulletin(error.text).show(); } } private void afterUploadingMedia() { + final StickerUploader stickerUploader = this.stickerUploader; + if (stickerUploader == null) { + return; + } final int currentAccount = UserConfig.selectedAccount; + stickerUploader.uploaded = true; + if (stickerUploader.customHandler != null) { + hideLoadingDialog(); + stickerUploader.customHandler.run(stickerUploader.finalPath, stickerUploader.tlInputStickerSetItem.document); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated), 250); + return; + } if (stickerUploader.replacedSticker != null) { TLRPC.TL_stickers_replaceSticker req = new TLRPC.TL_stickers_replaceSticker(); - req.sticker = MediaDataController.getInputStickerSetItem(stickerUploader.replacedSticker, "").document; + req.sticker = MediaDataController.getInputStickerSetItem(stickerUploader.replacedSticker, stickerUploader.emoji).document; req.new_sticker = stickerUploader.tlInputStickerSetItem; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document), 250); + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); + if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(set.set.id)) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); + } + if (loadingToast != null) { + loadingToast.setProgress(1f); + } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document, stickerUploader.thumbPath, true); + hideLoadingDialog(); + }, 450); + success = true; + } else { + showError(error); + hideLoadingDialog(); + } + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(success); + stickerUploader.whenDone = null; } - showError(error); - hideLoadingDialog(); })); } else if (stickerUploader.stickerPackName != null) { TLRPC.TL_stickers_createStickerSet req = new TLRPC.TL_stickers_createStickerSet(); @@ -1006,33 +1500,68 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. req.short_name = ""; req.stickers.add(stickerUploader.tlInputStickerSetItem); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; if (response instanceof TLRPC.TL_messages_stickerSet) { + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document), 250); + if (loadingToast != null) { + loadingToast.setProgress(1f); + } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document, stickerUploader.thumbPath, false); + hideLoadingDialog(); + }, 250); + success = true; + } else { + showError(error); + hideLoadingDialog(); + } + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(success); + stickerUploader.whenDone = null; } - showError(error); - hideLoadingDialog(); })); } else if (stickerUploader.addToFavorite) { hideLoadingDialog(); NotificationCenter.getInstance(currentAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false); AndroidUtilities.runOnUIThread(() -> MediaDataController.getInstance(UserConfig.selectedAccount).addRecentSticker(MediaDataController.TYPE_FAVE, null, stickerUploader.mediaDocument.document, (int) (System.currentTimeMillis() / 1000), false), 350); + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(true); + } } else if (stickerUploader.stickerSet != null) { TLRPC.TL_stickers_addStickerToSet req = new TLRPC.TL_stickers_addStickerToSet(); req.stickerset = MediaDataController.getInputStickerSet(stickerUploader.stickerSet); req.sticker = stickerUploader.tlInputStickerSetItem; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document), 250); + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); + if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(set.set.id)) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); + } + if (loadingToast != null) { + loadingToast.setProgress(1f); + } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document, stickerUploader.thumbPath, false); + hideLoadingDialog(); + }, 450); + success = true; + } else { + showError(error); + hideLoadingDialog(); + } + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(success); + stickerUploader.whenDone = null; } - showError(error); - hideLoadingDialog(); })); } } - private static class StickerUploader { + public static class StickerUploader { public String path; public String finalPath; public String emoji; @@ -1043,9 +1572,59 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. public boolean addToFavorite; public TLRPC.StickerSet stickerSet; public TLRPC.Document replacedSticker; + public String thumbPath; + public Utilities.Callback2 customHandler; + public Utilities.Callback whenDone; + public boolean uploaded; + + public ArrayList finalFiles = new ArrayList(); + public ArrayList files = new ArrayList(); public MessageObject messageObject; public VideoEditedInfo videoEditedInfo; + public int reqId; + + private float convertingProgress = 0, uploadProgress = 0; + public float getProgress() { + final float maxPercent = customHandler == null ? .9f : 1f; + if (videoEditedInfo == null) { + return maxPercent * uploadProgress; + } + return maxPercent * (.5f * convertingProgress + .5f * uploadProgress); + } + + public void setupFiles() { + if (!TextUtils.isEmpty(finalPath)) { + finalFiles.add(new File(finalPath)); + } + if (!TextUtils.isEmpty(path) && !TextUtils.equals(path, finalPath)) { + files.add(new File(path)); + } + if (!TextUtils.isEmpty(thumbPath)) { + files.add(new File(thumbPath)); + } + } + + public void destroy(boolean all) { + if (all) { + for (File file : finalFiles) { + try { + file.delete(); + } catch (Exception e) { + FileLog.e(e); + } + } + } + finalFiles.clear(); + for (File file : files) { + try { + file.delete(); + } catch (Exception e) { + FileLog.e(e); + } + } + files.clear(); + } } private static class Point extends android.graphics.Point { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java index 41386272b..9ad20883d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java @@ -349,7 +349,7 @@ public class TextPaintView extends EntityView { } public void setSwatch(Swatch swatch) { - this.swatch = swatch; + this.swatch = swatch.clone(); updateColor(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java index 7be320ebe..52973e071 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java @@ -58,6 +58,14 @@ public class PaintingOverlay extends FrameLayout { } } + public boolean drawChildren = true; + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (!drawChildren) return false; + return super.drawChild(canvas, child, drawingTime); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ignoreLayout = true; @@ -73,9 +81,14 @@ public class PaintingOverlay extends FrameLayout { } if (child instanceof EditTextOutline) { child.measure(MeasureSpec.makeMeasureSpec(entity.viewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - float sc = entity.textViewWidth * width / entity.viewWidth; - child.setScaleX(entity.scale * sc); - child.setScaleY(entity.scale * sc); + float scale; + if (entity.customTextView) { + scale = entity.width * getMeasuredWidth() / entity.viewWidth; + } else { + scale = entity.scale * (entity.textViewWidth * width / entity.viewWidth); + } + child.setScaleX(scale); + child.setScaleY(scale); } else { child.measure(MeasureSpec.makeMeasureSpec((int) (width * entity.width), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (height * entity.height), MeasureSpec.EXACTLY)); } @@ -118,15 +131,20 @@ public class PaintingOverlay extends FrameLayout { if (entity == null) { continue; } - int x, y; + int x, y, w = child.getMeasuredWidth(), h = child.getMeasuredHeight(); if (child instanceof EditTextOutline) { - x = (int) (width * entity.textViewX) - child.getMeasuredWidth() / 2; - y = (int) (height * entity.textViewY) - child.getMeasuredHeight() / 2; + if (entity.customTextView) { + x = (int) (width * (entity.x + entity.width / 2f)) - child.getMeasuredWidth() / 2; + y = (int) (height * (entity.y + entity.height / 2f)) - child.getMeasuredHeight() / 2; + } else { + x = (int) (width * entity.textViewX) - child.getMeasuredWidth() / 2; + y = (int) (height * entity.textViewY) - child.getMeasuredHeight() / 2; + } } else { x = (int) (width * entity.x); y = (int) (height * entity.y); } - child.layout(x, y, x + child.getMeasuredWidth(), y + child.getMeasuredHeight()); + child.layout(x, y, x + w, y + h); } } } @@ -169,7 +187,7 @@ public class PaintingOverlay extends FrameLayout { View child = null; if (entity.type == 0) { BackupImageView imageView = new BackupImageView(getContext()); - imageView.setLayerNum(8); + imageView.setLayerNum(4 | 8); imageView.setAspectFit(true); ImageReceiver imageReceiver = imageView.getImageReceiver(); if (isVideo) { @@ -187,7 +205,7 @@ public class PaintingOverlay extends FrameLayout { } } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(entity.document.thumbs, 90); - imageReceiver.setImage(ImageLocation.getForDocument(entity.document), null, ImageLocation.getForDocument(thumb, entity.document), null, "webp", entity.parentObject, 1); + imageReceiver.setImage(ImageLocation.getForDocument(entity.document), null, null, null, ImageLocation.getForDocument(thumb, entity.document), null, null, 0, "webp", entity.parentObject, 1); if ((entity.subType & 2) != 0) { imageView.setScaleX(-1); } @@ -212,6 +230,14 @@ public class PaintingOverlay extends FrameLayout { for (VideoEditedInfo.EmojiEntity e : entity.entities) { text.setSpan(new AnimatedEmojiSpan(e.document_id, editText.getPaint().getFontMetricsInt()), e.offset, e.offset + e.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } + if (text instanceof Spanned) { + Emoji.EmojiSpan[] spans = ((Spanned) text).getSpans(0, text.length(), Emoji.EmojiSpan.class); + if (spans != null) { + for (int i = 0; i < spans.length; ++i) { + spans[i].scale = .85f; + } + } + } editText.setText(text); editText.setGravity(Gravity.CENTER); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java index f30ecf63c..9144dfbfc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java @@ -27,6 +27,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; +import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -49,8 +50,10 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; @@ -91,7 +94,7 @@ public class PollVotesAlert extends BottomSheet { private ArrayList voters = new ArrayList<>(); - private TextView titleTextView; + private AnimatedEmojiSpan.TextViewEmojis titleTextView; private int scrollOffsetY; private int topBeforeSwitch; @@ -144,7 +147,7 @@ public class PollVotesAlert extends BottomSheet { public class SectionCell extends FrameLayout { - private TextView textView; + private AnimatedEmojiSpan.TextViewEmojis textView; private TextView middleTextView; private AnimatedTextView righTextView; @@ -153,7 +156,7 @@ public class PollVotesAlert extends BottomSheet { setBackgroundColor(Theme.getColor(Theme.key_graySection)); - textView = new TextView(getContext()); + textView = new AnimatedEmojiSpan.TextViewEmojis(getContext()); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(Theme.getColor(Theme.key_graySectionText)); @@ -221,8 +224,17 @@ public class PollVotesAlert extends BottomSheet { } - public void setText(String left, int percent, int votesCount, int collapsed, boolean animated) { - textView.setText(Emoji.replaceEmoji(left, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + public void setText(CharSequence left, ArrayList entities, int percent, int votesCount, int collapsed, boolean animated) { + if (entities != null) { + NotificationCenter.listenEmojiLoading(textView); + CharSequence answerText = new SpannableStringBuilder(left); + MediaDataController.addTextStyleRuns(entities, left, (Spannable) answerText); + answerText = Emoji.replaceEmoji(answerText, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); + MessageObject.replaceAnimatedEmoji(answerText, entities, textView.getPaint().getFontMetricsInt()); + textView.setText(answerText); + } else { + textView.setText(Emoji.replaceEmoji(left, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + } String p = String.format("%d", percent); SpannableStringBuilder builder; if (LocaleController.isRTL) { @@ -602,7 +614,7 @@ public class PollVotesAlert extends BottomSheet { Collections.sort(voters, new Comparator() { private int getIndex(VotesList votesList) { for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { return a; } @@ -902,13 +914,22 @@ public class PollVotesAlert extends BottomSheet { } }); - titleTextView = new TextView(context); + titleTextView = new AnimatedEmojiSpan.TextViewEmojis(context); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); titleTextView.setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(5), AndroidUtilities.dp(14), AndroidUtilities.dp(21)); titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); titleTextView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); - titleTextView.setText(Emoji.replaceEmoji(poll.question, titleTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false)); + if (poll.question != null && poll.question.entities != null) { + NotificationCenter.listenEmojiLoading(titleTextView); + CharSequence questionText = new SpannableStringBuilder(poll.question.text); + MediaDataController.addTextStyleRuns(poll.question.entities, poll.question.text, (Spannable) questionText); + questionText = Emoji.replaceEmoji(questionText, titleTextView.getPaint().getFontMetricsInt(), false); + MessageObject.replaceAnimatedEmoji(questionText, poll.question.entities, titleTextView.getPaint().getFontMetricsInt()); + titleTextView.setText(questionText); + } else { + titleTextView.setText(Emoji.replaceEmoji(poll.question == null ? "" : poll.question.text, titleTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false)); + } actionBar = new ActionBar(context) { @Override @@ -1160,13 +1181,13 @@ public class PollVotesAlert extends BottomSheet { view.setAlpha(1.0f); VotesList votesList = voters.get(section); for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { Button button = votesPercents.get(votesList); if (button == null) { continue; } - sectionCell.setText(answer.text, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); + sectionCell.setText(answer.text == null ? "" : answer.text.text, answer.text == null ? null : answer.text.entities, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); sectionCell.setTag(R.id.object_tag, votesList); break; } @@ -1217,13 +1238,13 @@ public class PollVotesAlert extends BottomSheet { VotesList votesList = voters.get(section); TLRPC.MessagePeerVote vote = votesList.votes.get(0); for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { Button button = votesPercents.get(votesList); if (button == null) { continue; } - sectionCell.setText(answer.text, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); + sectionCell.setText(answer.text == null ? "" : answer.text.text, answer.text == null ? null : answer.text.entities, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); sectionCell.setTag(R.id.object_tag, votesList); break; } @@ -1314,13 +1335,13 @@ public class PollVotesAlert extends BottomSheet { SectionCell sectionCell = (SectionCell) child; VotesList votesList = (VotesList) child.getTag(R.id.object_tag); for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { Button button = votesPercents.get(votesList); if (button == null) { continue; } - sectionCell.setText(answer.text, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), true); + sectionCell.setText(answer.text == null ? "" : answer.text.text, answer.text == null ? null : answer.text.entities, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), true); sectionCell.setTag(R.id.object_tag, votesList); break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java index c806a759d..fb76976ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java @@ -202,7 +202,7 @@ public class PopupSwipeBackLayout extends FrameLayout { p.updateAnimation = false; p.setBackScaleX(w / p.getMeasuredWidth()); if (applyBackScaleY) { - p.setBackScaleY(h / p.getMeasuredHeight()); + p.setBackScaleY(Math.min(1, h / p.getMeasuredHeight())); } p.updateAnimation = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java index 34beeaa62..78c45ab94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java @@ -335,7 +335,7 @@ public class FeaturesPageView extends BaseListPageView { Canvas canvas = new Canvas(bitmap); canvas.drawColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_premiumGradient2, resourcesProvider), Theme.getColor(Theme.key_dialogBackground, resourcesProvider), 0.5f)); iconTextureView.setBackgroundBitmap(bitmap); - iconTextureView.mRenderer.forceNight = true; +// iconTextureView.mRenderer.forceNight = true; iconTextureView.mRenderer.colorKey1 = Theme.key_premiumGradient2; iconTextureView.mRenderer.colorKey2 = Theme.key_premiumGradient1; iconTextureView.mRenderer.updateColors(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java index 8f4da1e58..d93617d13 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java @@ -43,8 +43,8 @@ public class GLIconRenderer implements GLSurfaceView.Renderer { int color1; int color2; - public int colorKey1 = Theme.key_premiumStartGradient1; - public int colorKey2 = Theme.key_premiumStartGradient2; + public int colorKey1 = Theme.key_premiumStarGradient1; + public int colorKey2 = Theme.key_premiumStarGradient2; private final int style; private final int type; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java index 6fd3fafca..758be97f7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java @@ -88,7 +88,8 @@ public class Icon3D { private static final String[] coinModel = new String[] { "models/coin_outer.binobj", "models/coin_inner.binobj", - "models/coin_logo.binobj" + "models/coin_logo.binobj", + "models/coin_stars.binobj" }; public Icon3D(Context context, int type) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java index 4c891c19c..083c1b29c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java @@ -71,7 +71,7 @@ public class PremiumButtonView extends FrameLayout implements Loadable { flickerDrawable.repeatProgress = 4f; LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); - buttonTextView = new AnimatedTextView(context) { + buttonTextView = new AnimatedTextView(context, true, true, true) { @Override protected void onDraw(Canvas canvas) { if (loadingT > 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java index 26de5b8bd..c49a511db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java @@ -492,38 +492,14 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i titleView = new LinkSpanDrawable.LinksTextView[2]; for (int a = 0; a < 2; ++a) { titleView[a] = new LinkSpanDrawable.LinksTextView(context, resourcesProvider) { - private Layout lastLayout; - AnimatedEmojiSpan.EmojiGroupedSpans stack; - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - AnimatedEmojiSpan.release(this, stack); - lastLayout = null; - } - - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - if (lastLayout != getLayout()) { - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, this, stack, lastLayout = getLayout()); - } - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), stack, 0, null, 0, 0, 0, 1f, colorFilter); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(99999999, MeasureSpec.AT_MOST)); - } - - @Override - public int overrideColor() { - return accentColor != null ? Theme.multAlpha(accentColor, .10f) : super.overrideColor(); + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; } }; titleView[a].setVisibility(a == 0 ? View.VISIBLE : View.GONE); titleView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - titleView[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView[a].setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleView[a].setGravity(Gravity.CENTER_HORIZONTAL); titleView[a].setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); titleView[a].setLinkTextColor(getThemedColor(Theme.key_windowBackgroundWhiteLinkText)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java index fc3554d4c..873299054 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java @@ -45,6 +45,7 @@ import org.telegram.ui.Components.Premium.StarParticlesView; import org.telegram.ui.Components.Premium.boosts.cells.DurationWithDiscountCell; import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; import java.util.ArrayList; import java.util.Collections; @@ -101,12 +102,13 @@ public class PremiumPreviewGiftToUsersBottomSheet extends PremiumPreviewBottomSh @Override public void setTitle(boolean animated) { titleView[0].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - subtitleView.setPadding(dp(30), 0, dp(30), 0); - subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f); - titleView[0].setText(getString("GiftTelegramPremiumTitle", R.string.GiftTelegramPremiumTitle)); ((ViewGroup.MarginLayoutParams) subtitleView.getLayoutParams()).bottomMargin = dp(16); ((ViewGroup.MarginLayoutParams) subtitleView.getLayoutParams()).topMargin = dp(4f); + subtitleView.setPadding(dp(30), 0, dp(30), 0); + subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f); + + titleView[0].setText(getString("GiftTelegramPremiumTitle", R.string.GiftTelegramPremiumTitle)); String subTitle; switch (selectedUsers.size()) { case 1: { @@ -220,7 +222,7 @@ public class PremiumPreviewGiftToUsersBottomSheet extends PremiumPreviewBottomSh TLRPC.TL_premiumGiftCodeOption giftCodeOption = getSelectedOption(); String priceStr = BillingController.getInstance().formatCurrency(giftCodeOption.amount, giftCodeOption.currency); if (selectedUsers.size() == 1) { - actionBtn.setText(formatString("GiftSubscriptionFor", R.string.GiftSubscriptionFor, priceStr), animated); + actionBtn.setText(formatString(R.string.GiftSubscriptionFor, priceStr), animated); } else { actionBtn.setText(formatPluralString("GiftSubscriptionCountFor", selectedUsers.size(), priceStr), animated); } @@ -251,23 +253,33 @@ public class PremiumPreviewGiftToUsersBottomSheet extends PremiumPreviewBottomSh return; } actionBtn.setLoading(true); - BoostRepository.payGiftCode(new ArrayList<>(selectedUsers), getSelectedOption(), null, getBaseFragment(), result -> { - dismiss(); - NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.giftsToUserSent); - AndroidUtilities.runOnUIThread(() -> PremiumPreviewGiftSentBottomSheet.show(selectedUsers), 250); - }, error -> { - actionBtn.setLoading(false); - BoostDialogs.showToastError(getContext(), error); - }); + if (isSelf()) { + PremiumPreviewFragment.buyPremium(getBaseFragment(), "grace_period"); + } else { + BoostRepository.payGiftCode(new ArrayList<>(selectedUsers), getSelectedOption(), null, getBaseFragment(), result -> { + dismiss(); + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.giftsToUserSent); + AndroidUtilities.runOnUIThread(() -> PremiumPreviewGiftSentBottomSheet.show(selectedUsers), 250); + }, error -> { + actionBtn.setLoading(false); + BoostDialogs.showToastError(getContext(), error); + }); + } }); buttonContainer.addView(actionBtn, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); - overrideTitleIcon = AvatarHolderView.createAvatarsContainer(getContext(), selectedUsers); + if (!isSelf()) { + overrideTitleIcon = AvatarHolderView.createAvatarsContainer(getContext(), selectedUsers); + } updateActionButton(false); fixNavigationBar(); } + public boolean isSelf() { + return selectedUsers.size() == 1 && selectedUsers.get(0) != null && selectedUsers.get(0).id == UserConfig.getInstance(getCurrentAccount()).getClientUserId(); + } + protected void afterCellCreated(int viewType, View view) { if (viewType == 0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java index 65a00b84a..0ac039d88 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java @@ -486,7 +486,7 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView { View child = recyclerListView.getChildAt(i); if (child instanceof SelectorUserCell) { int position = recyclerListView.getChildAdapterPosition(child); - if (position < 0) { + if (position - 1 < 0 || position - 1 >= items.size()) { continue; } Item item = items.get(position - 1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java index 8c3f1ddeb..1693defd0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java @@ -11,6 +11,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.net.Uri; +import android.os.Bundle; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -18,6 +19,7 @@ import android.text.style.ReplacementSpan; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; +import android.widget.FrameLayout; import android.widget.LinearLayout; import androidx.annotation.NonNull; @@ -32,17 +34,26 @@ import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.browser.Browser; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextCell; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.ItemOptions; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter; import org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter.Item; @@ -51,7 +62,10 @@ import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorHeaderCe import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorSearchCell; import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorUserCell; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.DialogsActivity; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PrivacyControlActivity; +import org.telegram.ui.ProfileActivity; import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import java.util.ArrayList; @@ -120,6 +134,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp private final View sectionCell; private final SelectorHeaderCell headerView; private final SelectorBtnCell buttonContainer; + private final FrameLayout bulletinContainer; private final ArrayList oldItems = new ArrayList<>(); private final ArrayList items = new ArrayList<>(); @@ -274,6 +289,9 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + bulletinContainer = new FrameLayout(getContext()); + containerView.addView(bulletinContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, 300, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(68))); + selectorAdapter.setData(items, recyclerListView); recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(BOTTOM_HEIGHT_DP)); recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -285,6 +303,10 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp } }); recyclerListView.setOnItemClickListener((view, position, x, y) -> { + if (view instanceof TextCell) { + openBirthdaySetup(); + return; + } if (view instanceof SelectorUserCell) { TLRPC.User user = ((SelectorUserCell) view).getUser(); long id = user.id; @@ -404,6 +426,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp public void onAttachedToWindow() { super.onAttachedToWindow(); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.giftsToUserSent); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.userInfoDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.contactsDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadHints); } @@ -412,6 +435,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp public void onDetachedFromWindow() { super.onDetachedFromWindow(); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.giftsToUserSent); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.contactsDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.reloadHints); } @@ -523,7 +547,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp } count++; h += dp(56); - userItems.add(Item.asUser(user, selectedIds.contains(user.id))); + userItems.add(Item.asUser(user, selectedIds.contains(user.id)).withOptions(openOptions(user))); } if (userItems.isEmpty()) { return h; @@ -570,9 +594,17 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp if (isSearching()) { for (TLRPC.User foundedUser : foundedUsers) { h += dp(56); - items.add(Item.asUser(foundedUser, selectedIds.contains(foundedUser.id))); + items.add(Item.asUser(foundedUser, selectedIds.contains(foundedUser.id)).withOptions(openOptions(foundedUser))); } } else { + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); + if (userFull == null) { + MessagesController.getInstance(currentAccount).loadFullUser(UserConfig.getInstance(currentAccount).getCurrentUser(), 0, true); + } + if (userFull != null && userFull.birthday == null) { + h += dp(50); + items.add(Item.asButton(1, R.drawable.menu_birthday, getString(R.string.GiftsBirthdaySetup))); + } if (userId >= 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userId); if (user != null) { @@ -598,7 +630,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp } if (selectedIds.contains(user.id)) selected.add(user.id); h += dp(56); - userItems.add(Item.asUser(user, selectedIds.contains(user.id))); + userItems.add(Item.asUser(user, selectedIds.contains(user.id)).withOptions(openOptions(user))); } if (!userItems.isEmpty()) { h += dp(32); @@ -620,7 +652,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp h += dp(56); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(contact.user_id); if (selectedIds.contains(user.id)) selected.add(user.id); - userItems.add(Item.asUser(user, selectedIds.contains(user.id))); + userItems.add(Item.asUser(user, selectedIds.contains(user.id)).withOptions(openOptions(user))); } if (!userItems.isEmpty()) { @@ -662,6 +694,33 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp } } + public View.OnClickListener openOptions(TLRPC.User user) { + return (View view) -> { + ItemOptions.makeOptions(container, resourcesProvider, (View) view.getParent()) + .add(R.drawable.profile_discuss, LocaleController.getString(R.string.SendMessage), () -> { + BaseFragment fragment = getBaseFragment(); + if (user == null || fragment == null) return; + BaseFragment.BottomSheetParams bottomSheetParams = new BaseFragment.BottomSheetParams(); + bottomSheetParams.transitionFromLeft = true; + bottomSheetParams.allowNestedScroll = false; + Bundle args = new Bundle(); + args.putLong("user_id", user.id); + fragment.showAsSheet(new ChatActivity(args), bottomSheetParams); + }) + .add(R.drawable.msg_openprofile, LocaleController.getString(R.string.OpenProfile), () -> { + BaseFragment fragment = getBaseFragment(); + if (user == null || fragment == null) return; + BaseFragment.BottomSheetParams bottomSheetParams = new BaseFragment.BottomSheetParams(); + bottomSheetParams.transitionFromLeft = true; + bottomSheetParams.allowNestedScroll = false; + Bundle args = new Bundle(); + args.putLong("user_id", user.id); + fragment.showAsSheet(new ProfileActivity(args), bottomSheetParams); + }) + .show(); + }; + } + @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -694,6 +753,65 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp AndroidUtilities.runOnUIThread(() -> initContacts(true)); } else if (id == NotificationCenter.reloadHints) { AndroidUtilities.runOnUIThread(() -> initHints(true)); + } else if (id == NotificationCenter.userInfoDidLoad) { + AndroidUtilities.runOnUIThread(() -> updateItems(true, true)); } } + + private void openBirthdaySetup() { + AlertsCreator.createBirthdayPickerDialog(getContext(), getString(R.string.EditProfileBirthdayTitle), getString(R.string.EditProfileBirthdayButton), null, birthday -> { + TLRPC.TL_account_updateBirthday req = new TLRPC.TL_account_updateBirthday(); + req.flags |= 1; + req.birthday = birthday; + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); + TLRPC.TL_birthday oldBirthday = userFull != null ? userFull.birthday : null; + if (userFull != null) { + userFull.flags2 |= 32; + userFull.birthday = birthday; + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TLRPC.TL_boolTrue) { + BulletinFactory.of(bulletinContainer, resourcesProvider) + .createSimpleBulletin(R.raw.contact_check, LocaleController.getString(R.string.PrivacyBirthdaySetDone)) + .setDuration(Bulletin.DURATION_PROLONG) + .show(); + } else { + if (userFull != null) { + if (oldBirthday == null) { + userFull.flags2 &=~ 32; + } else { + userFull.flags2 |= 32; + } + userFull.birthday = oldBirthday; + MessagesStorage.getInstance(currentAccount).updateUserInfo(userFull, false); + } + if (err != null && err.text != null && err.text.startsWith("FLOOD_WAIT_")) { + if (getContext() != null) { + new AlertDialog.Builder(getContext(), resourcesProvider) + .setTitle(getString(R.string.PrivacyBirthdayTooOftenTitle)) + .setMessage(getString(R.string.PrivacyBirthdayTooOftenMessage)) + .setPositiveButton(getString(R.string.OK), null) + .show(); + } + } else { + BulletinFactory.of(bulletinContainer, resourcesProvider) + .createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.UnknownError)) + .show(); + } + } + }), ConnectionsManager.RequestFlagDoNotWaitFloodWait); + + MessagesController.getInstance(currentAccount).removeSuggestion(0, "BIRTHDAY_SETUP"); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.newSuggestionsAvailable); + updateItems(true, true); + }, () -> { + if (getBaseFragment() == null) { + return; + } + BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams(); + params.transitionFromLeft = true; + params.allowNestedScroll = false; + getBaseFragment().showAsSheet(new PrivacyControlActivity(PrivacyControlActivity.PRIVACY_RULES_TYPE_BIRTHDAY), params); + }, resourcesProvider).show(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java index dd95d46f6..d08c9b113 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java @@ -21,6 +21,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.GraySectionCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.Premium.boosts.BoostRepository; import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorCountryCell; @@ -41,6 +42,7 @@ public class SelectorAdapter extends AdapterWithDiffUtils { public static final int VIEW_TYPE_COUNTRY = 6; public static final int VIEW_TYPE_LETTER = 7; public static final int VIEW_TYPE_TOP_SECTION = 8; + public static final int VIEW_TYPE_BUTTON = 9; private final Theme.ResourcesProvider resourcesProvider; private final Context context; @@ -82,7 +84,7 @@ public class SelectorAdapter extends AdapterWithDiffUtils { @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { - return (holder.getItemViewType() == VIEW_TYPE_USER || holder.getItemViewType() == VIEW_TYPE_COUNTRY); + return (holder.getItemViewType() == VIEW_TYPE_USER || holder.getItemViewType() == VIEW_TYPE_COUNTRY || holder.getItemViewType() == VIEW_TYPE_BUTTON); } @NonNull @@ -105,6 +107,11 @@ public class SelectorAdapter extends AdapterWithDiffUtils { view = new SelectorCountryCell(context, resourcesProvider); } else if (viewType == VIEW_TYPE_TOP_SECTION) { view = new GraySectionCell(context, resourcesProvider); + } else if (viewType == VIEW_TYPE_BUTTON) { + TextCell cell = new TextCell(context, resourcesProvider); + cell.leftPadding = 23 - 7; + cell.imageLeft = 19; + view = cell; } else { view = new View(context); } @@ -157,6 +164,7 @@ public class SelectorAdapter extends AdapterWithDiffUtils { if ((position + 1 < items.size()) && items.get(position + 1).viewType == VIEW_TYPE_LETTER) { userCell.setDivider(false); } + userCell.setOptions(item.options); } else if (viewType == VIEW_TYPE_COUNTRY) { SelectorCountryCell cell = (SelectorCountryCell) holder.itemView; boolean needDivider = (position < items.size() - 1) && (position + 1 < items.size() - 1) && (items.get(position + 1).viewType != VIEW_TYPE_LETTER); @@ -189,6 +197,10 @@ public class SelectorAdapter extends AdapterWithDiffUtils { } } topSectionCell = cell; + } else if (viewType == VIEW_TYPE_BUTTON) { + TextCell cell = (TextCell) holder.itemView; + cell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); + cell.setTextAndIcon(item.text, item.resId, false); } } @@ -274,9 +286,12 @@ public class SelectorAdapter extends AdapterWithDiffUtils { public TLRPC.TL_help_country country; public CharSequence text, subtext; public int type; + public int id; + public int resId; public boolean checked; public int padHeight = -1; public View.OnClickListener callback; + public View.OnClickListener options; private Item(int viewType, boolean selectable) { super(viewType, selectable); @@ -288,6 +303,14 @@ public class SelectorAdapter extends AdapterWithDiffUtils { return item; } + public static Item asButton(int id, int resId, String text) { + Item item = new Item(VIEW_TYPE_BUTTON, false); + item.id = id; + item.resId = resId; + item.text = text; + return item; + } + public static Item asUser(TLRPC.User user, boolean checked) { Item item = new Item(VIEW_TYPE_USER, true); item.user = user; @@ -297,6 +320,11 @@ public class SelectorAdapter extends AdapterWithDiffUtils { return item; } + public Item withOptions(View.OnClickListener onClickListener) { + this.options = onClickListener; + return this; + } + public static Item asLetter(String letter) { Item item = new Item(VIEW_TYPE_LETTER, false); item.text = letter; @@ -369,6 +397,8 @@ public class SelectorAdapter extends AdapterWithDiffUtils { return false; } else if (viewType == VIEW_TYPE_TOP_SECTION && (!TextUtils.equals(text, i.text))) { return false; + } else if (viewType == VIEW_TYPE_BUTTON && (!TextUtils.equals(text, i.text) || id != i.id || resId != i.resId)) { + return false; } return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java index 01916702e..180f8025f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java @@ -6,6 +6,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.widget.LinearLayout; +import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.RecyclerListView; @@ -33,6 +34,6 @@ public class SelectorBtnCell extends LinearLayout { } else { dividerPaint.setAlpha((int) (0xFF * alpha.set(1))); } - canvas.drawRect(0, 0, getWidth(), 1, dividerPaint); + canvas.drawRect(0, 0, getWidth(), AndroidUtilities.getShadowHeight(), dividerPaint); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java index fc28f0bc1..85a14e0e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java @@ -4,8 +4,12 @@ import static org.telegram.messenger.AndroidUtilities.dp; import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.ColorFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.view.Gravity; import android.view.View; +import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -30,6 +34,7 @@ public class SelectorUserCell extends BaseCell { private final boolean[] isOnline = new boolean[1]; private final CheckBox2 checkBox; + private final ImageView optionsView; private TLRPC.User user; private TLRPC.Chat chat; private TL_stories.TL_myBoost boost; @@ -51,6 +56,21 @@ public class SelectorUserCell extends BaseCell { addView(checkBox); checkBox.setChecked(false, false); checkBox.setLayoutParams(LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 13, 0, 14, 0)); + + optionsView = new ImageView(context); + optionsView.setScaleType(ImageView.ScaleType.CENTER); + optionsView.setImageResource(R.drawable.ic_ab_other); + optionsView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_inMenu, resourcesProvider), PorterDuff.Mode.SRC_IN)); + addView(optionsView, LayoutHelper.createFrame(32, 32, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 12, 0, 12, 0)); + } + + public void setOptions(View.OnClickListener listener) { + if (listener != null) { + optionsView.setVisibility(View.VISIBLE); + optionsView.setOnClickListener(listener); + } else { + optionsView.setVisibility(View.GONE); + } } @Override @@ -96,6 +116,7 @@ public class SelectorUserCell extends BaseCell { } public void setUser(TLRPC.User user) { + optionsView.setVisibility(View.GONE); this.user = user; this.chat = null; avatarDrawable.setInfo(user); @@ -110,6 +131,8 @@ public class SelectorUserCell extends BaseCell { } public void setChat(TLRPC.Chat chat, int participants_count) { + optionsView.setVisibility(View.GONE); + this.chat = chat; this.user = null; avatarDrawable.setInfo(chat); @@ -134,6 +157,8 @@ public class SelectorUserCell extends BaseCell { } public void setBoost(TL_stories.TL_myBoost boost) { + optionsView.setVisibility(View.GONE); + this.boost = boost; this.chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(boost.peer)); 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 02dcce0bc..c779c43b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -54,6 +54,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma public static native long create(String src, String json, int w, int h, int[] params, boolean precache, int[] colorReplacement, boolean limitFps, int fitzModifier); public static native long getFramesCount(String src, String json); + public static native double getDuration(String src, String json); protected static native long createWithJson(String json, String name, int[] params, int[] colorReplacement); 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 7de61dc83..0f5f6d6f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java @@ -136,18 +136,24 @@ public class RLottieImageView extends ImageView { } }; imageReceiver.setAllowLoadingOnAttachedOnly(true); + ImageLocation thumbLocation = null; + String thumbFilter = null; + if (document.localThumbPath != null) { + thumbLocation = ImageLocation.getForPath(document.localThumbPath); + thumbFilter = w + "_" + h; + } if (onlyLastFrame) { - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + "_lastframe", null, null, null, null, null, 0, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + "_lastframe", null, null, thumbLocation, thumbFilter, null, 0, null, document, 1); } else if ("video/webm".equals(document.mime_type)) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : "") + "_" + ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(thumb, document), null, null, document.size, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : "") + "_" + ImageLoader.AUTOPLAY_FILTER, thumbLocation != null ? thumbLocation : ImageLocation.getForDocument(thumb, document), thumbFilter, null, document.size, null, document, 1); } else { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); if (svgThumb != null) { svgThumb.overrideWidthAndHeight(512, 512); } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : ""), ImageLocation.getForDocument(thumb, document), null, null, null, svgThumb, 0, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : ""), ImageLocation.getForDocument(thumb, document), null, thumbLocation, thumbFilter, svgThumb, 0, null, document, 1); } imageReceiver.setAspectFit(true); imageReceiver.setParentView(this); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java index 594a3b2b1..b65ff39c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java @@ -265,10 +265,8 @@ public class ReactedUsersListView extends FrameLayout { AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> { if (response instanceof TLRPC.TL_messages_messageReactionsList) { TLRPC.TL_messages_messageReactionsList res = (TLRPC.TL_messages_messageReactionsList) response; - - for (TLRPC.User u : res.users) { - MessagesController.getInstance(currentAccount).putUser(u, false); - } + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); HashSet visibleCustomEmojiReactions = new HashSet<>(); for (int i = 0; i < res.reactions.size(); i++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java index 3fc8967c1..ddfacc698 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java @@ -31,6 +31,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; @@ -38,6 +39,7 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.SlideIntChooseView; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.ChatActivity; @@ -66,6 +68,7 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not private LinearLayout switchLayout; private LinearLayout contentLayout; private CustomReactionEditText editText; + private SlideIntChooseView slideView; private UpdateReactionsButton actionButton; private ScrollView scrollView; @@ -78,6 +81,7 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not private boolean emojiKeyboardVisible = false; private final TLRPC.ChatFull info; private final long chatId; + private int currentReactionsCount, reactionsCount; private TLRPC.Chat currentChat; private TL_stories.TL_premium_boostsStatus boostsStatus; private int selectedCustomReactions; @@ -205,16 +209,36 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not TextInfoPrivacyCell infoCell2 = new TextInfoPrivacyCell(context); infoCell2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4)); - infoCell2.setTopPadding(12); - infoCell2.setBottomPadding(70); infoCell2.setText(AndroidUtilities.replaceSingleTag( - LocaleController.getString("ReactionCreateOwnPack", R.string.ReactionCreateOwnPack), + getString(R.string.ReactionCreateOwnPack), Theme.key_chat_messageLinkIn, 0, - () -> presentFragment(ChatActivity.of(429000)), + () -> Browser.openUrl(getContext(), "https://t.me/stickers"), getResourceProvider() )); switchLayout.addView(infoCell2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + HeaderCell headerCell1 = new HeaderCell(context, resourceProvider); + headerCell1.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + headerCell1.setText(getString(R.string.MaximumReactionsHeader)); + switchLayout.addView(headerCell1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + slideView = new SlideIntChooseView(context, resourceProvider); + slideView.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + if (info instanceof TLRPC.TL_chatFull ? (info.flags & 1048576) != 0 : (info.flags2 & 8192) != 0) { + currentReactionsCount = reactionsCount = info.reactions_limit; + } else { + currentReactionsCount = reactionsCount = getMessagesController().reactionsUniqMax; + } + slideView.set(reactionsCount, SlideIntChooseView.Options.make(0, "MaximumReactionsValue", 1, getMessagesController().reactionsUniqMax), value -> { + reactionsCount = value; + }); + switchLayout.addView(slideView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + TextInfoPrivacyCell infoCell3 = new TextInfoPrivacyCell(context); + infoCell3.setTopPadding(12); + infoCell3.setBottomPadding(70); + infoCell3.setText(LocaleController.getString(R.string.MaximumReactionsInfo)); + switchLayout.addView(infoCell3, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + actionButton = new UpdateReactionsButton(context, getResourceProvider()); actionButton.setDefaultState(); actionButton.setOnClickListener(v -> { @@ -228,7 +252,7 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not } actionButton.setLoading(true); - getMessagesController().setCustomChatReactions(chatId, selectedType, grabReactions(false), error -> { + getMessagesController().setCustomChatReactions(chatId, selectedType, grabReactions(false), currentReactionsCount = reactionsCount, error -> { if (isFinishing()) { return; } @@ -576,8 +600,8 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not public void onFragmentDestroy() { super.onFragmentDestroy(); AndroidUtilities.cancelRunOnUIThread(checkAfterFastDeleteRunnable); - if (selectedType == SELECT_TYPE_NONE) { - getMessagesController().setCustomChatReactions(chatId, selectedType, new ArrayList<>(), null, null); + if (selectedType == SELECT_TYPE_NONE && reactionsCount != currentReactionsCount) { + getMessagesController().setCustomChatReactions(chatId, selectedType, grabReactions(false), reactionsCount, null, null); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java index 7cca87513..b378b15ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java @@ -226,7 +226,7 @@ public class ChatSelectionReactionMenuOverlay extends FrameLayout { reactionsContainerLayout.setVisibility(VISIBLE); if (!messageSet) { messageSet = true; - reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo()); + reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo(), true); } } } @@ -352,7 +352,7 @@ public class ChatSelectionReactionMenuOverlay extends FrameLayout { if (reactionsContainerLayout.isEnabled()) { messageSet = true; - reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo()); + reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo(), true); reactionsContainerLayout.startEnterAnimation(false); } else { messageSet = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java index ab5b8413d..e6de8c9ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java @@ -1,5 +1,6 @@ package org.telegram.ui.Components.Reactions; +import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STICKER_SET_EMOJI; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY_LIKES; @@ -76,6 +77,7 @@ public class CustomEmojiReactionsWindow { float fromRadius; RectF fromRect = new RectF(); + float fromRectTranslateX, fromRectTranslateY; public RectF drawingRect = new RectF(); float enterTransitionProgress; boolean enterTransitionFinished; @@ -233,7 +235,7 @@ public class CustomEmojiReactionsWindow { @Override public void getOutline(View view, Outline outline) { - float radius = AndroidUtilities.lerp(fromRadius, AndroidUtilities.dp(8), enterTransitionProgress); + float radius = AndroidUtilities.lerp(fromRadius, dp(8), enterTransitionProgress); rectTmp.set(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); AndroidUtilities.lerp(fromRect, rectTmp, enterTransitionProgress, rectF); rectF.round(rect); @@ -298,9 +300,9 @@ public class CustomEmojiReactionsWindow { return; } float y = yTranslation; - int bottomOffset = AndroidUtilities.dp(32); + int bottomOffset = dp(32); if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { - bottomOffset = AndroidUtilities.dp(24); + bottomOffset = dp(24); } if (y + containerView.getMeasuredHeight() > windowView.getMeasuredHeight() - keyboardHeight - bottomOffset) { y = windowView.getMeasuredHeight() - keyboardHeight - containerView.getMeasuredHeight() - bottomOffset; @@ -350,26 +352,26 @@ public class CustomEmojiReactionsWindow { reactionsContainerLayout.getLocationOnScreen(location); } windowView.getLocationOnScreen(windowLocation); - float y = location[1] - windowLocation[1] - AndroidUtilities.dp(44) - AndroidUtilities.dp(52) - (selectAnimatedEmojiDialog.includeHint ? AndroidUtilities.dp(26) : 0) + reactionsContainerLayout.getTopOffset(); + float y = location[1] - windowLocation[1] - dp(44) - dp(52) - (selectAnimatedEmojiDialog.includeHint ? dp(26) : 0) + reactionsContainerLayout.getTopOffset(); if (reactionsContainerLayout.showExpandableReactions()) { - y = location[1] - windowLocation[1] - AndroidUtilities.dp(12); + y = location[1] - windowLocation[1] - dp(12); } - if (y + containerView.getMeasuredHeight() > windowView.getMeasuredHeight() - AndroidUtilities.dp(32)) { - y = windowView.getMeasuredHeight() - AndroidUtilities.dp(32) - containerView.getMeasuredHeight(); + if (y + containerView.getMeasuredHeight() > windowView.getMeasuredHeight() - dp(32)) { + y = windowView.getMeasuredHeight() - dp(32) - containerView.getMeasuredHeight(); } - if (y < AndroidUtilities.dp(16)) { - y = AndroidUtilities.dp(16); + if (y < dp(16)) { + y = dp(16); } if (type == TYPE_STORY) { - containerView.setTranslationX((windowView.getMeasuredWidth() - containerView.getMeasuredWidth()) / 2f - AndroidUtilities.dp(16)); + containerView.setTranslationX((windowView.getMeasuredWidth() - containerView.getMeasuredWidth()) / 2f - dp(16)); } else if (type == TYPE_STORY_LIKES || type == TYPE_STICKER_SET_EMOJI) { - containerView.setTranslationX(location[0] - windowLocation[0] - AndroidUtilities.dp(18)); + containerView.setTranslationX(location[0] - windowLocation[0] - dp(18)); } else { - containerView.setTranslationX(location[0] - windowLocation[0] - AndroidUtilities.dp(2)); + containerView.setTranslationX(location[0] - windowLocation[0] - dp(2)); } if (!enter) { @@ -379,7 +381,10 @@ public class CustomEmojiReactionsWindow { containerView.setTranslationY(yTranslation); } - fromRect.offset(location[0] - windowLocation[0] - containerView.getX(), location[1] - windowLocation[1] - containerView.getY()); + fromRect.offset( + fromRectTranslateX = location[0] - windowLocation[0] - containerView.getX(), + fromRectTranslateY = location[1] - windowLocation[1] - containerView.getY() + ); reactionsContainerLayout.setCustomEmojiEnterProgress(enterTransitionProgress); @@ -397,7 +402,10 @@ public class CustomEmojiReactionsWindow { selectAnimatedEmojiDialog.emojiTabs.showRecentTabStub(enter && cascadeAnimation); account = UserConfig.selectedAccount; notificationsLocker.lock(); - valueAnimator = StableAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0); + if (valueAnimator != null) { + valueAnimator.cancel(); + } + valueAnimator = type == TYPE_STICKER_SET_EMOJI ? ValueAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0) : StableAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0); valueAnimator.addUpdateListener(animation -> { valueAnimator = null; enterTransitionProgress = (float) animation.getAnimatedValue(); @@ -441,7 +449,10 @@ public class CustomEmojiReactionsWindow { } }); - if (cascadeAnimation) { + if (type == TYPE_STICKER_SET_EMOJI) { + valueAnimator.setDuration(420); + valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + } else if (cascadeAnimation) { valueAnimator.setDuration(450); valueAnimator.setInterpolator(new OvershootInterpolator(0.5f)); } else { @@ -571,8 +582,13 @@ public class CustomEmojiReactionsWindow { checkAnimationEnd(enter); } }); - valueAnimator.setDuration(350); - valueAnimator.setInterpolator(new OvershootInterpolator(1f)); + if (type == TYPE_STICKER_SET_EMOJI) { + valueAnimator.setDuration(420); + valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + } else { + valueAnimator.setDuration(350); + valueAnimator.setInterpolator(new OvershootInterpolator(1f)); + } valueAnimator.start(); } } @@ -639,6 +655,9 @@ public class CustomEmojiReactionsWindow { if (dismissed) { return; } + if (reactionsContainerLayout != null) { + reactionsContainerLayout.onCustomEmojiWindowClosing(); + } Bulletin.hideVisible(); dismissed = true; AndroidUtilities.hideKeyboard(windowView); @@ -717,7 +736,7 @@ public class CustomEmojiReactionsWindow { public ContainerView(@NonNull Context context) { super(context); shadow = ContextCompat.getDrawable(context, R.drawable.reactions_bubble_shadow).mutate(); - shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = AndroidUtilities.dp(7); + shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = dp(7); shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow, resourcesProvider), PorterDuff.Mode.MULTIPLY)); if (type == TYPE_STORY_LIKES) { backgroundPaint.setColor(ColorUtils.blendARGB(Color.BLACK, Color.WHITE, 0.13f)); @@ -741,18 +760,20 @@ public class CustomEmojiReactionsWindow { size = reactionsContainerLayout.getMeasuredWidth(); } else { size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); - int measuredSize = AndroidUtilities.dp(36) * 8 + AndroidUtilities.dp(12); + int measuredSize = dp(36) * 8 + dp(12); if (measuredSize < size) { size = measuredSize; } } int height = size; - if (reactionsContainerLayout.showExpandableReactions()) { + if (type == TYPE_STICKER_SET_EMOJI) { + height = dp(36) * 8 - dp(8); + } else if (reactionsContainerLayout.showExpandableReactions()) { int rows = (int) Math.ceil(reactions.size() / 8f); if (rows <= 8) { - height = rows * AndroidUtilities.dp(36) + AndroidUtilities.dp(8); + height = rows * dp(36) + dp(8); } else { - height = AndroidUtilities.dp(36) * 8 - AndroidUtilities.dp(8); + height = dp(36) * 8 - dp(8); } } super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); @@ -773,8 +794,12 @@ public class CustomEmojiReactionsWindow { } float progressClpamped = Utilities.clamp(enterTransitionProgress,1f, 0f); AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + if (type == TYPE_STICKER_SET_EMOJI) { + fromRect.set(reactionsContainerLayout.rect); + fromRect.offset(fromRectTranslateX, fromRectTranslateY); + } AndroidUtilities.lerp(fromRect, AndroidUtilities.rectTmp, enterTransitionProgress, drawingRect); - float radius = AndroidUtilities.lerp(fromRadius, AndroidUtilities.dp(8), enterTransitionProgress); + float radius = AndroidUtilities.lerp(fromRadius, dp(8), enterTransitionProgress); transitionReactions.clear(); @@ -810,10 +835,10 @@ public class CustomEmojiReactionsWindow { enterTransitionScalePy = 0; if (reactionsContainerLayout != null) { - for (int i = 0; i < selectAnimatedEmojiDialog.emojiGridView.getChildCount(); i++) { + for (int i = selectAnimatedEmojiDialog.emojiGridView.getChildCount() - 1; i >= 0; --i) { if (selectAnimatedEmojiDialog.emojiGridView.getChildAt(i) instanceof SelectAnimatedEmojiDialog.ImageViewEmoji) { SelectAnimatedEmojiDialog.ImageViewEmoji imageViewEmoji = (SelectAnimatedEmojiDialog.ImageViewEmoji) selectAnimatedEmojiDialog.emojiGridView.getChildAt(i); - if (imageViewEmoji.reaction != null) { + if (imageViewEmoji.isFirstReactions && imageViewEmoji.reaction != null) { transitionReactions.put(imageViewEmoji.reaction, imageViewEmoji); } } @@ -831,7 +856,7 @@ public class CustomEmojiReactionsWindow { int top = (int) (selectAnimatedEmojiDialog.getX() + selectAnimatedEmojiDialog.emojiGridView.getX()); int left = (int) (selectAnimatedEmojiDialog.getY() + selectAnimatedEmojiDialog.emojiGridView.getY()); boolean isEmojiTabsVisible = selectAnimatedEmojiDialog.emojiTabs.getParent() != null; - canvas.clipRect(left, isEmojiTabsVisible ? top + AndroidUtilities.dp(36) * enterTransitionProgress : 0, left + selectAnimatedEmojiDialog.emojiGridView.getMeasuredWidth(), top + selectAnimatedEmojiDialog.emojiGridView.getMeasuredHeight()); + canvas.clipRect(left, isEmojiTabsVisible ? top + dp(36) * enterTransitionProgress : 0, left + selectAnimatedEmojiDialog.emojiGridView.getMeasuredWidth(), top + selectAnimatedEmojiDialog.emojiGridView.getMeasuredHeight()); for (int i = -1; i < reactionsContainerLayout.recyclerListView.getChildCount(); i++) { View child; if (i == -1) { @@ -865,11 +890,19 @@ public class CustomEmojiReactionsWindow { fromX -= reactionsContainerLayout.recyclerListView.getX(); fromY -= reactionsContainerLayout.recyclerListView.getY(); } - float toX = toImageView.getX() + selectAnimatedEmojiDialog.getX() + selectAnimatedEmojiDialog.emojiGridView.getX() - holderView.loopImageView.getX() - AndroidUtilities.dp(1); + float toX = toImageView.getX() + selectAnimatedEmojiDialog.getX() + selectAnimatedEmojiDialog.emojiGridView.getX() - holderView.loopImageView.getX() - dp(1); float toY = toImageView.getY() + selectAnimatedEmojiDialog.getY() + selectAnimatedEmojiDialog.gridViewContainer.getY() + selectAnimatedEmojiDialog.emojiGridView.getY() - holderView.loopImageView.getY(); float toImageViewSize = toImageView.getMeasuredWidth(); - if (toImageView.selected) { - float sizeAfterScale = toImageViewSize * (0.8f + 0.2f * 0.3f); + if (toImageView.selected || type == TYPE_STICKER_SET_EMOJI) { + float sizeAfterScale = toImageViewSize; + if (type == TYPE_STICKER_SET_EMOJI) { + sizeAfterScale *= .87f; + toX -= dp(.33f); + toY -= dp(1.33f); + } + if (toImageView.selected) { + sizeAfterScale *= (0.8f + 0.2f * 0.3f); + } toX += (toImageViewSize - sizeAfterScale) / 2f; toY += (toImageViewSize - sizeAfterScale) / 2f; toImageViewSize = sizeAfterScale; @@ -881,10 +914,10 @@ public class CustomEmojiReactionsWindow { float toScale = toImageViewSize / (float) holderView.loopImageView.getMeasuredWidth(); scale = AndroidUtilities.lerp(1f, toScale, enterTransitionProgress); if (holderView.position == 0) { - fromRoundRadiusLb = fromRoundRadiusLt = AndroidUtilities.dp(6); + fromRoundRadiusLb = fromRoundRadiusLt = dp(6); fromRoundRadiusRb = fromRoundRadiusRt = 0; } else if (holderView.selected) { - fromRoundRadiusRb = fromRoundRadiusLb = fromRoundRadiusRt = fromRoundRadiusLt = AndroidUtilities.dp(6); + fromRoundRadiusRb = fromRoundRadiusLb = fromRoundRadiusRt = fromRoundRadiusLt = dp(6); } canvas.translate(dX, dY); @@ -905,11 +938,11 @@ public class CustomEmojiReactionsWindow { if (toImageView.selected) { float cx = holderView.getMeasuredWidth() / 2f; float cy = holderView.getMeasuredHeight() / 2f; - float fromSize = holderView.getMeasuredWidth() - AndroidUtilities.dp(2); - float toSize = toImageView.getMeasuredWidth() - AndroidUtilities.dp(2); + float fromSize = holderView.getMeasuredWidth() - dp(2); + float toSize = toImageView.getMeasuredWidth() - dp(2); float finalSize = AndroidUtilities.lerp(fromSize, toSize / scale, enterTransitionProgress); AndroidUtilities.rectTmp.set(cx - finalSize / 2f, cy - finalSize / 2f, cx + finalSize / 2f, cy + finalSize / 2f); - float rectRadius = AndroidUtilities.lerp(fromSize / 2f, AndroidUtilities.dp(4), enterTransitionProgress); + float rectRadius = AndroidUtilities.lerp(fromSize / 2f, dp(4), enterTransitionProgress); canvas.drawRoundRect(AndroidUtilities.rectTmp, rectRadius, rectRadius, selectAnimatedEmojiDialog.selectorPaint); } holderView.drawSelected = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java index d42a0903f..23f350e1e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java @@ -19,6 +19,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.RLottieDrawable; import java.util.Objects; @@ -96,6 +97,25 @@ public class ReactionImageHolder { } } + public boolean isLoaded() { + ImageReceiver imageReceiver; + if (animatedEmojiDrawable != null) { + imageReceiver = animatedEmojiDrawable.getImageReceiver(); + } else { + imageReceiver = this.imageReceiver; + } + if (imageReceiver == null) return false; + if (!imageReceiver.hasImageSet()) return false; + if (!imageReceiver.hasImageLoaded()) return false; + RLottieDrawable rLottieDrawable = imageReceiver.getLottieAnimation(); + if (rLottieDrawable != null) { + if (rLottieDrawable.isGeneratingCache()) { + return false; + } + } + return true; + } + public void setBounds(Rect bounds) { this.bounds.set(bounds); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java index 71cd9ed33..4750ad568 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -51,6 +51,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LiteMode; @@ -151,7 +152,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio private float bigCircleRadius = dp(8); private float smallCircleRadius = bigCircleRadius / 2; public int bigCircleOffset = dp(36); - private MessageObject messageObject; + public MessageObject messageObject; + public boolean hitLimit; private int currentAccount; private long waitingLoadingChatId; private boolean isTop; @@ -167,10 +169,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio private List visibleReactionsList = new ArrayList<>(20); private List premiumLockedReactions = new ArrayList<>(10); - private List allReactionsList = new ArrayList<>(20); + public List allReactionsList = new ArrayList<>(20); private LinearLayoutManager linearLayoutManager; - private RecyclerView.Adapter listAdapter; + private Adapter listAdapter; RectF rectF = new RectF(); HashSet selectedReactions = new HashSet<>(); @@ -348,114 +350,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio }); recyclerListView.setLayoutManager(linearLayoutManager); recyclerListView.setOverScrollMode(View.OVER_SCROLL_NEVER); - recyclerListView.setAdapter(listAdapter = new AdapterWithDiffUtils() { - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - return false; - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View view; - switch (viewType) { - default: - case VIEW_TYPE_REACTION: - case VIEW_TYPE_CUSTOM_REACTION: - view = new ReactionHolderView(context, true); - break; - case VIEW_TYPE_PREMIUM_BUTTON: - premiumLockContainer = new FrameLayout(context); - premiumLockIconView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_REACTIONS); - premiumLockIconView.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), Theme.getColor(Theme.key_dialogBackground), 0.7f)); - premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - premiumLockIconView.setScaleX(0f); - premiumLockIconView.setScaleY(0f); - premiumLockIconView.setPadding(dp(1), dp(1), dp(1), dp(1)); - premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); - premiumLockIconView.setOnClickListener(v -> { - int[] position = new int[2]; - v.getLocationOnScreen(position); - showUnlockPremium(position[0] + v.getMeasuredWidth() / 2f, position[1] + v.getMeasuredHeight() / 2f); - }); - view = premiumLockContainer; - break; - case VIEW_TYPE_CUSTOM_EMOJI_BUTTON: - customReactionsContainer = new CustomReactionsContainer(context); - customEmojiReactionsIconView = new InternalImageView(context); - customEmojiReactionsIconView.setImageResource(R.drawable.msg_reactions_expand); - customEmojiReactionsIconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - if (type == TYPE_STORY || type == TYPE_STORY_LIKES || type == TYPE_STICKER_SET_EMOJI) { - customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); - } else { - customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - } - customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); - customEmojiReactionsIconView.setPadding(dp(2), dp(2), dp(2), dp(2)); - customEmojiReactionsIconView.setContentDescription(LocaleController.getString(R.string.AccDescrExpandPanel)); - customReactionsContainer.addView(customEmojiReactionsIconView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); - customEmojiReactionsIconView.setOnClickListener(v -> { - showCustomEmojiReactionDialog(); - }); - view = customReactionsContainer; - break; - } - - int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); - view.setLayoutParams(new RecyclerView.LayoutParams(size - dp(12), size)); - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { - ReactionHolderView h = (ReactionHolderView) holder.itemView; - h.setScaleX(1); - h.setScaleY(1); - h.setReaction(items.get(position).reaction, position); - } - } - - @Override - public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { - int position = holder.getAdapterPosition(); - if (position >= 0 && position < items.size()) { - ((ReactionHolderView) holder.itemView).updateSelected(items.get(position).reaction); - } - } - super.onViewAttachedToWindow(holder); - } - - @Override - public int getItemCount() { - return items.size(); - } - - @Override - public int getItemViewType(int position) { - return items.get(position).viewType; - } - - @Override - public void notifyDataSetChanged() { - oldItems.clear(); - oldItems.addAll(items); - items.clear(); - for (int i = 0; i < visibleReactionsList.size(); i++) { - ReactionsLayoutInBubble.VisibleReaction visibleReaction = visibleReactionsList.get(i); - items.add(new InnerItem(visibleReaction.emojicon == null ? VIEW_TYPE_CUSTOM_REACTION : VIEW_TYPE_REACTION, visibleReaction)); - } - if (showUnlockPremiumButton()) { - items.add(new InnerItem(VIEW_TYPE_PREMIUM_BUTTON, null)); - } - if (showCustomEmojiReaction()) { - items.add(new InnerItem(VIEW_TYPE_CUSTOM_EMOJI_BUTTON, null)); - } - setItems(oldItems, items); - } - }); + recyclerListView.setAdapter(listAdapter = new Adapter()); recyclerListView.addOnScrollListener(new LeftRightShadowsListener()); recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -556,6 +451,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio private void animatePullingBack() { if (pullingLeftOffset != 0) { + if (pullingDownBackAnimator != null) { + pullingDownBackAnimator.cancel(); + } pullingDownBackAnimator = ValueAnimator.ofFloat(pullingLeftOffset, 0); pullingDownBackAnimator.addUpdateListener(animation -> { pullingLeftOffset = (float) pullingDownBackAnimator.getAnimatedValue(); @@ -654,7 +552,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } @SuppressLint("NotifyDataSetChanged") - private void setVisibleReactionsList(List visibleReactionsList) { + private void setVisibleReactionsList(List visibleReactionsList, boolean animated) { this.visibleReactionsList.clear(); if (showCustomEmojiReaction()) { int i = 0; @@ -687,9 +585,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (size * visibleReactionsList.size() < dp(200)) { getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; } - - listAdapter.notifyDataSetChanged(); - + listAdapter.updateItems(animated); } @Override @@ -989,6 +885,22 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio view.setScaleY(otherViewsScale); } + private void invalidateEmojis() { + if (type != TYPE_STICKER_SET_EMOJI) return; + invalidate(); + recyclerListView.invalidate(); + recyclerListView.invalidateViews(); + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + View child = recyclerListView.getChildAt(i); + if (child instanceof ReactionHolderView) { + ((ReactionHolderView) child).enterImageView.invalidate(); + ((ReactionHolderView) child).loopImageView.invalidate(); + } else { + child.invalidate(); + } + } + } + private void checkPressedProgress(Canvas canvas, ReactionHolderView view) { float pullingOffsetX = 0; if (pullingLeftOffset != 0) { @@ -1091,8 +1003,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio invalidate(); } - public void setMessage(MessageObject message, TLRPC.ChatFull chatFull) { + public void setMessage(MessageObject message, TLRPC.ChatFull chatFull, boolean animated) { this.messageObject = message; + hitLimit = type == TYPE_DEFAULT && messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.reactions != null && messageObject.messageOwner.reactions.results.size() >= MessagesController.getInstance(currentAccount).getChatMaxUniqReactions(messageObject.getDialogId()); TLRPC.ChatFull reactionsChat = chatFull; List visibleReactions = new ArrayList<>(); if (message != null && message.isForwardedChannelPost()) { @@ -1107,6 +1020,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (type == TYPE_TAGS) { allReactionsAvailable = UserConfig.getInstance(currentAccount).isPremium(); fillRecentReactionsList(visibleReactions); + } else if (hitLimit) { + allReactionsAvailable = false; + for (TLRPC.ReactionCount result : messageObject.messageOwner.reactions.results) { + visibleReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(result.reaction)); + } } else if (reactionsChat != null) { if (reactionsChat.available_reactions instanceof TLRPC.TL_chatReactionsAll) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(reactionsChat.id); @@ -1139,14 +1057,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio fillRecentReactionsList(visibleReactions); } filterReactions(visibleReactions); - showExpandableReactions = !allReactionsAvailable && visibleReactions.size() > 16 || allReactionsAvailable && !UserConfig.getInstance(currentAccount).isPremium() && MessagesController.getInstance(currentAccount).premiumFeaturesBlocked(); + showExpandableReactions = !hitLimit && (!allReactionsAvailable && visibleReactions.size() > 16 || allReactionsAvailable && !UserConfig.getInstance(currentAccount).isPremium() && MessagesController.getInstance(currentAccount).premiumFeaturesBlocked()); if (type == TYPE_TAGS && !UserConfig.getInstance(currentAccount).isPremium()) { showExpandableReactions = false; } if (type == TYPE_STICKER_SET_EMOJI) { showExpandableReactions = true; } - setVisibleReactionsList(visibleReactions); + setVisibleReactionsList(visibleReactions, animated); if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { for (int i = 0; i < message.messageOwner.reactions.results.size(); i++) { @@ -1251,20 +1169,22 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio selectedReactions.clear(); selectedReactions.addAll(getInclusiveReactions(messages)); updateSelected(); - if (type == TYPE_STICKER_SET_EMOJI) { - alwaysSelectedReactions.addAll(selectedReactions); - setMessage(messageObject, null); - } } public void setSelectedReactionInclusive(ReactionsLayoutInBubble.VisibleReaction visibleReaction) { selectedReactions.clear(); selectedReactions.add(visibleReaction); updateSelected(); - if (type == TYPE_STICKER_SET_EMOJI) { - alwaysSelectedReactions.addAll(selectedReactions); - setMessage(messageObject, null); + } + + public void setSelectedEmojis(ArrayList emojis) { + selectedReactions.clear(); + for (String emoji : emojis) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji); + selectedReactions.add(reaction); + alwaysSelectedReactions.add(reaction); } + updateSelected(); } private void updateSelected() { @@ -1283,8 +1203,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (set.contains(visibleReactions.get(i))) { i--; visibleReactions.remove(i); + } else { + set.add(visibleReactions.get(i)); } - set.add(visibleReactions.get(i)); } } @@ -1292,13 +1213,25 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio HashSet hashSet = new HashSet<>(); int added = 0; if (type == TYPE_STICKER_SET_EMOJI) { - for (ReactionsLayoutInBubble.VisibleReaction visibleReaction : alwaysSelectedReactions) { + for (ReactionsLayoutInBubble.VisibleReaction visibleReaction : selectedReactions) { if (!hashSet.contains(visibleReaction)) { hashSet.add(visibleReaction); visibleReactions.add(visibleReaction); added++; + if (added >= 8) return; } } + List enabledReactions = MediaDataController.getInstance(currentAccount).getEnabledReactionsList(); + for (int i = 0; i < enabledReactions.size(); i++) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(enabledReactions.get(i)); + if (!hashSet.contains(visibleReaction)) { + hashSet.add(visibleReaction); + visibleReactions.add(visibleReaction); + added++; + if (added >= 8) return; + } + } + return; } if (!allReactionsAvailable || type == TYPE_STICKER_SET_EMOJI) { if (type == TYPE_TAGS) { @@ -1513,6 +1446,21 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } public void onCustomEmojiWindowOpened() { + if (pullingDownBackAnimator != null) { + pullingDownBackAnimator.cancel(); + } + pullingLeftOffset = 0f; + if (customReactionsContainer != null) { + customReactionsContainer.invalidate(); + } + invalidate(); + } + + + public void onCustomEmojiWindowClosing() { + if (pullingDownBackAnimator != null) { + pullingDownBackAnimator.cancel(); + } pullingLeftOffset = 0f; if (customReactionsContainer != null) { customReactionsContainer.invalidate(); @@ -1528,7 +1476,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio MediaDataController.getInstance(currentAccount).clearRecentReactions(); List visibleReactions = new ArrayList<>(); fillRecentReactionsList(visibleReactions); - setVisibleReactionsList(visibleReactions); + setVisibleReactionsList(visibleReactions, true); lastVisibleViews.clear(); reactionsWindow.setRecentReactions(visibleReactions); }) @@ -1912,9 +1860,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int position) { + selected = selectedReactions.contains(react); if (currentReaction != null && currentReaction.equals(react)) { this.position = position; - selected = selectedReactions.contains(react); updateImage(react); return; } @@ -1932,7 +1880,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio resetAnimation(); currentReaction = react; - selected = selectedReactions.contains(react); hasEnterAnimation = currentReaction.emojicon != null && (showCustomEmojiReaction() || allReactionsIsDefault) && LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS); if (type == TYPE_STICKER_SET_EMOJI) { hasEnterAnimation = false; @@ -1986,7 +1933,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } private void updateImage(ReactionsLayoutInBubble.VisibleReaction react) { - if (currentReaction.emojicon != null) { + if (type == TYPE_STICKER_SET_EMOJI && react != null && react.emojicon != null) { + enterImageView.getImageReceiver().setImageBitmap(Emoji.getEmojiDrawable(react.emojicon)); + loopImageView.getImageReceiver().setImageBitmap(Emoji.getEmojiDrawable(react.emojicon)); + } else if (currentReaction.emojicon != null) { TLRPC.TL_availableReaction defaultReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(currentReaction.emojicon); if (defaultReaction != null) { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(defaultReaction.activate_animation, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); @@ -2235,12 +2185,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatInfoDidLoad); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatInfoDidLoad); } @@ -2249,10 +2201,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (id == NotificationCenter.chatInfoDidLoad) { TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0]; if (chatFull.id == waitingLoadingChatId && getVisibility() != View.VISIBLE && !(chatFull.available_reactions instanceof TLRPC.TL_chatReactionsNone)) { - setMessage(messageObject, null); + setMessage(messageObject, null, true); setVisibility(View.VISIBLE); startEnterAnimation(false); } + } else if (id == NotificationCenter.emojiLoaded) { + invalidateEmojis(); } } @@ -2380,4 +2334,116 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public static boolean allowSmoothEnterTransition() { return SharedConfig.deviceIsHigh(); } + + public class Adapter extends AdapterWithDiffUtils { + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + switch (viewType) { + default: + case VIEW_TYPE_REACTION: + case VIEW_TYPE_CUSTOM_REACTION: + view = new ReactionHolderView(getContext(), true); + break; + case VIEW_TYPE_PREMIUM_BUTTON: + premiumLockContainer = new FrameLayout(getContext()); + premiumLockIconView = new PremiumLockIconView(getContext(), PremiumLockIconView.TYPE_REACTIONS); + premiumLockIconView.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), Theme.getColor(Theme.key_dialogBackground), 0.7f)); + premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + premiumLockIconView.setScaleX(0f); + premiumLockIconView.setScaleY(0f); + premiumLockIconView.setPadding(dp(1), dp(1), dp(1), dp(1)); + premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); + premiumLockIconView.setOnClickListener(v -> { + int[] position = new int[2]; + v.getLocationOnScreen(position); + showUnlockPremium(position[0] + v.getMeasuredWidth() / 2f, position[1] + v.getMeasuredHeight() / 2f); + }); + view = premiumLockContainer; + break; + case VIEW_TYPE_CUSTOM_EMOJI_BUTTON: + customReactionsContainer = new CustomReactionsContainer(getContext()); + customEmojiReactionsIconView = new InternalImageView(getContext()); + customEmojiReactionsIconView.setImageResource(R.drawable.msg_reactions_expand); + customEmojiReactionsIconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES || type == TYPE_STICKER_SET_EMOJI) { + customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + } else { + customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + } + customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); + customEmojiReactionsIconView.setPadding(dp(2), dp(2), dp(2), dp(2)); + customEmojiReactionsIconView.setContentDescription(LocaleController.getString(R.string.AccDescrExpandPanel)); + customReactionsContainer.addView(customEmojiReactionsIconView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); + customEmojiReactionsIconView.setOnClickListener(v -> { + showCustomEmojiReactionDialog(); + }); + view = customReactionsContainer; + break; + } + + int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); + view.setLayoutParams(new RecyclerView.LayoutParams(size - dp(12), size)); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { + ReactionHolderView h = (ReactionHolderView) holder.itemView; + h.setScaleX(1); + h.setScaleY(1); + h.setReaction(items.get(position).reaction, position); + } + } + + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { + int position = holder.getAdapterPosition(); + if (position >= 0 && position < items.size()) { + ((ReactionHolderView) holder.itemView).updateSelected(items.get(position).reaction); + } + } + super.onViewAttachedToWindow(holder); + } + + @Override + public int getItemCount() { + return items.size(); + } + + @Override + public int getItemViewType(int position) { + return items.get(position).viewType; + } + + public void updateItems(boolean animated) { + oldItems.clear(); + oldItems.addAll(items); + items.clear(); + for (int i = 0; i < visibleReactionsList.size(); i++) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = visibleReactionsList.get(i); + items.add(new InnerItem(visibleReaction.emojicon == null ? VIEW_TYPE_CUSTOM_REACTION : VIEW_TYPE_REACTION, visibleReaction)); + } + if (showUnlockPremiumButton()) { + items.add(new InnerItem(VIEW_TYPE_PREMIUM_BUTTON, null)); + } + if (showCustomEmojiReaction()) { + items.add(new InnerItem(VIEW_TYPE_CUSTOM_EMOJI_BUTTON, null)); + } + if (animated) { + setItems(oldItems, items); + } else { + super.notifyDataSetChanged(); + } + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java index 6c8cc6ad5..102836da4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java @@ -48,6 +48,7 @@ public class ReplyMessageLine { private Path color2Path = new Path(); private Path color3Path = new Path(); private int switchedCount = 0; + private float emojiAlpha = 1f; private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emoji; @@ -179,23 +180,17 @@ public class ReplyMessageLine { messageObject.messageOwner != null && ( (messageObject.isFromUser() || DialogObject.isEncryptedDialog(messageObject.getDialogId())) && currentUser != null || messageObject.isFromChannel() && currentChat != null || - messageObject.isSponsored() && messageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || - messageObject.isSponsored() && messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null || - messageObject.messageOwner != null && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.from_id != null + messageObject.messageOwner != null && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.from_id != null || + messageObject.isSponsored() && messageObject.sponsoredColor != null && messageObject.sponsoredColor.color != -1 ) )) { int colorId = 5; if (messageObject.overrideLinkColor >= 0) { colorId = messageObject.overrideLinkColor; - } else if (messageObject.isSponsored() && messageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { - colorId = messageObject.sponsoredChatInvite.color; - if (type == TYPE_LINK && messageObject.sponsoredChatInvite.chat != null) { - emojiDocumentId = ChatObject.getEmojiId(messageObject.sponsoredChatInvite.chat); - } - } else if (messageObject.isSponsored() && messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { - colorId = ChatObject.getColorId(messageObject.sponsoredChatInvite.chat); + } else if (messageObject.isSponsored() && messageObject.sponsoredColor != null && messageObject.sponsoredColor.color != -1) { + colorId = messageObject.sponsoredColor.color; if (type == TYPE_LINK) { - emojiDocumentId = ChatObject.getEmojiId(messageObject.sponsoredChatInvite.chat); + emojiDocumentId = messageObject.sponsoredColor.background_emoji_id; } } else if (messageObject.messageOwner != null && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.from_id != null) { long dialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.fwd_from.from_id); @@ -330,6 +325,11 @@ public class ReplyMessageLine { return nameColorAnimated.set(nameColor); } + public void setEmojiAlpha(float emojiAlpha) { + this.emojiAlpha = emojiAlpha; + } + + public void resetAnimation() { color1Animated.set(color1, true); color2Animated.set(color2, true); @@ -509,7 +509,7 @@ public class ReplyMessageLine { if (emoji != null) { final float loadedScale = emojiLoadedT.set(isEmojiLoaded()); - if (loadedScale > 0) { + if (loadedScale > 0 && emojiAlpha > 0) { if (iconCoords == null) { iconCoords = new IconCoords[]{ new IconCoords(4, -6.33f, 1f, 1f), @@ -543,7 +543,7 @@ public class ReplyMessageLine { if (c.q && !hasQuote) { continue; } - emoji.setAlpha((int) (0xFF * .30f * c.a)); + emoji.setAlpha((int) (0xFF * .30f * c.a * emojiAlpha)); final float cx = x0 - dp(c.x); final float cy = y0 + dp(c.y); final float sz = dp(10) * c.s * loadedScale; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java index ffa394361..4921e3ad7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java @@ -42,4 +42,9 @@ public class ScaleStateListAnimator { view.setStateListAnimator(scaleStateListAnimator); } + + public static void reset(View view) { + view.setStateListAnimator(null); + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index 0d00e521a..029e7b274 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -642,7 +642,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { TLRPC.TL_messages_stickerSet stickerSet = ((TLRPC.TL_messages_stickerSet) parentObject); thumbVersion = ((TLRPC.TL_messages_stickerSet) parentObject).set.thumb_version; if (!tabView.inited) { - tabView.svgThumb = DocumentObject.getSvgThumb(stickerSet.set.thumbs, Theme.key_emptyListPlaceholder, 0.2f); + tabView.svgThumb = DocumentObject.getSvgThumb(stickerSet.set.thumbs, Theme.key_emptyListPlaceholder, 0.2f, DocumentObject.containsPhotoSizeType(stickerSet.set.thumbs, "v")); } } thumbType = thumb.type; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java index 051666196..f0cf72172 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java @@ -441,8 +441,8 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { layoutParams.weight = 0.0f; layoutParams.width = LayoutHelper.WRAP_CONTENT; } else { - layoutParams.weight = 1.0f / allTextWidth * positionToWidth.get(a); - layoutParams.width = 0; + layoutParams.weight = AndroidUtilities.lerp(1.0f / count, 1.0f / allTextWidth * positionToWidth.get(a), .5f); + layoutParams.width = LayoutHelper.WRAP_CONTENT; } } } 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 7494d5536..a8062cd24 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java @@ -11,8 +11,11 @@ import android.graphics.drawable.AnimatedVectorDrawable; import android.os.Build; import android.os.Bundle; import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.util.Log; import android.view.View; +import android.view.ViewGroup; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import android.widget.TextView; @@ -26,13 +29,18 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -46,6 +54,7 @@ import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.ui.Adapters.FiltersView; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.DialogCell; +import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HashtagSearchCell; import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.SharedAudioCell; @@ -53,6 +62,7 @@ import org.telegram.ui.Cells.SharedDocumentCell; import org.telegram.ui.Cells.SharedLinkCell; import org.telegram.ui.Cells.SharedPhotoVideoCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.DialogsActivity; import org.telegram.ui.FilteredSearchView; @@ -63,7 +73,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Set; -public class SearchViewPager extends ViewPagerFixed implements FilteredSearchView.UiCallback { +public class SearchViewPager extends ViewPagerFixed implements FilteredSearchView.UiCallback, NotificationCenter.NotificationCenterDelegate { protected final ViewPagerAdapter viewPagerAdapter; public FrameLayout searchContainer; @@ -75,6 +85,13 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie private RecyclerItemsEnterAnimator itemsEnterAnimator; private boolean attached; + private DefaultItemAnimator channelsItemAnimator; + public FrameLayout channelsSearchContainer; + public StickerEmptyView channelsEmptyView; + private LinearLayoutManager channelsSearchLayoutManager; + public RecyclerListView channelsSearchListView; + public DialogsChannelsAdapter channelsSearchAdapter; + private NumberTextView selectedMessagesCountTextView; private boolean isActionModeShowed; private HashMap selectedFiles = new HashMap<>(); @@ -220,8 +237,6 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie noMediaFiltersSearchView.setVisibility(View.GONE); noMediaFiltersSearchView.setChatPreviewDelegate(chatPreviewDelegate); - searchContainer = new FrameLayout(context); - FlickerLoadingView loadingView = new FlickerLoadingView(context); loadingView.setViewType(1); emptyView = new StickerEmptyView(context, loadingView, StickerEmptyView.STICKER_TYPE_SEARCH) { @@ -240,6 +255,7 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie emptyView.addView(loadingView, 0); emptyView.showProgress(true, false); + searchContainer = new FrameLayout(context); searchContainer.addView(emptyView); searchContainer.addView(searchListView); searchContainer.addView(noMediaFiltersSearchView); @@ -252,6 +268,82 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie } }); + channelsSearchContainer = new FrameLayout(context); + + channelsItemAnimator = new DefaultItemAnimator() { + @Override + protected void onMoveAnimationUpdate(RecyclerView.ViewHolder holder) { + super.onMoveAnimationUpdate(holder); + invalidate(); + } + }; + channelsItemAnimator.setSupportsChangeAnimations(false); + channelsItemAnimator.setDelayAnimations(false); + channelsItemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + channelsItemAnimator.setDurations(350); + + channelsSearchListView = new BlurredRecyclerView(context); + channelsSearchListView.setItemAnimator(channelsItemAnimator); + channelsSearchListView.setPivotY(0); + channelsSearchListView.setVerticalScrollBarEnabled(true); + channelsSearchListView.setInstantClick(true); + channelsSearchListView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT); + channelsSearchListView.setLayoutManager(channelsSearchLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + channelsSearchListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA); + + loadingView = new FlickerLoadingView(context); + loadingView.setViewType(1); + channelsEmptyView = new StickerEmptyView(context, loadingView, StickerEmptyView.STICKER_TYPE_SEARCH) { + @Override + public void setVisibility(int visibility) { + if (noMediaFiltersSearchView.getTag() != null) { + super.setVisibility(View.GONE); + return; + } + super.setVisibility(visibility); + } + }; + channelsEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + channelsEmptyView.subtitle.setVisibility(View.GONE); + channelsEmptyView.setVisibility(View.GONE); + channelsEmptyView.addView(loadingView, 0); + channelsEmptyView.showProgress(true, false); + channelsSearchContainer.addView(channelsEmptyView); + channelsSearchContainer.addView(channelsSearchListView); + channelsSearchListView.setEmptyView(channelsEmptyView); + channelsSearchListView.setAdapter(channelsSearchAdapter = new DialogsChannelsAdapter(channelsSearchListView, context, currentAccount, folderId, null) { + @Override + public void update(boolean animated) { + super.update(animated); + channelsEmptyView.showProgress(loadingMessages || loadingChannels || messages == null || !messages.isEmpty() || searchMyChannels == null || !searchMyChannels.isEmpty() || searchChannels == null || !searchChannels.isEmpty() || searchRecommendedChannels == null || !searchRecommendedChannels.isEmpty(), animated); + if (TextUtils.isEmpty(query)) { + channelsEmptyView.title.setText(LocaleController.getString(R.string.NoChannelsTitle)); + channelsEmptyView.subtitle.setVisibility(View.VISIBLE); + channelsEmptyView.subtitle.setText(LocaleController.getString(R.string.NoChannelsMessage)); + } else { + channelsEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + channelsEmptyView.subtitle.setVisibility(View.GONE); + } + } + + @Override + protected void hideKeyboard() { + AndroidUtilities.hideKeyboard(fragment.getParentActivity().getCurrentFocus()); + } + }); + channelsSearchListView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + AndroidUtilities.hideKeyboard(fragment.getParentActivity().getCurrentFocus()); + } + } + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + channelsSearchAdapter.checkBottom(); + } + }); + itemsEnterAnimator = new RecyclerItemsEnterAnimator(searchListView, true); setAdapter(viewPagerAdapter = new ViewPagerAdapter()); @@ -312,7 +404,11 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie } } - if (view == searchContainer) { + if (view == channelsSearchContainer) { + MessagesController.getInstance(currentAccount).getChannelRecommendations(0); + channelsSearchAdapter.search(query); + channelsEmptyView.setKeyboardHeight(keyboardSize, false); + } else if (view == searchContainer) { if (dialogId == 0 && minDate == 0 && maxDate == 0 || forumDialogId != 0) { lastSearchScrolledToTop = false; dialogsSearchAdapter.searchDialogs(query, includeFolder ? 1 : 0); @@ -779,6 +875,9 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie if (dialogsSearchAdapter.getItemCount() > 0) { searchLayoutManager.scrollToPositionWithOffset(0, 0); } + if (channelsSearchLayoutManager != null) { + channelsSearchLayoutManager.scrollToPositionWithOffset(0, 0); + } viewsByType.clear(); } @@ -805,6 +904,8 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie noMediaFiltersSearchView.setKeyboardHeight(keyboardSize, animated); } else if (getChildAt(i) instanceof SearchDownloadsContainer) { ((SearchDownloadsContainer) getChildAt(i)).setKeyboardHeight(keyboardSize, animated); + } else if (getChildAt(i) == channelsSearchContainer) { + channelsEmptyView.setKeyboardHeight(keyboardSize, animated); } } } @@ -872,13 +973,35 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.channelRecommendationsLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogDeleted); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogsNeedReload); attached = true; + + if (channelsSearchAdapter != null) { + channelsSearchAdapter.update(false); + } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); attached = false; + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.channelRecommendationsLoaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogDeleted); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogsNeedReload); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.channelRecommendationsLoaded) { + channelsEmptyView.showProgress(MessagesController.getInstance(currentAccount).getChannelRecommendations(0) != null, true); + channelsSearchAdapter.updateMyChannels(); + channelsSearchAdapter.update(true); + } else if (id == NotificationCenter.dialogDeleted || id == NotificationCenter.dialogsNeedReload) { + channelsSearchAdapter.updateMyChannels(); + channelsSearchAdapter.update(true); + } } @Override @@ -893,7 +1016,7 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie } public void showDownloads() { - setPosition(2); + setPosition(3); } public int getPositionForType(int initialSearchType) { @@ -910,8 +1033,9 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie ArrayList items = new ArrayList<>(); private final static int DIALOGS_TYPE = 0; - private final static int DOWNLOADS_TYPE = 1; - private final static int FILTER_TYPE = 2; + private final static int CHANNELS_TYPE = 1; + private final static int DOWNLOADS_TYPE = 2; + private final static int FILTER_TYPE = 3; public ViewPagerAdapter() { updateItems(); @@ -920,6 +1044,7 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie public void updateItems() { items.clear(); items.add(new Item(DIALOGS_TYPE)); + items.add(new Item(CHANNELS_TYPE)); if (!showOnlyDialogsAdapter) { Item item = new Item(FILTER_TYPE); item.filterIndex = 0; @@ -945,9 +1070,11 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie @Override public String getItemTitle(int position) { if (items.get(position).type == DIALOGS_TYPE) { - return LocaleController.getString("SearchAllChatsShort", R.string.SearchAllChatsShort); + return LocaleController.getString(R.string.SearchAllChatsShort); + } else if (items.get(position).type == CHANNELS_TYPE) { + return LocaleController.getString(R.string.ChannelsTab); } else if (items.get(position).type == DOWNLOADS_TYPE) { - return LocaleController.getString("DownloadsTabs", R.string.DownloadsTabs); + return LocaleController.getString(R.string.DownloadsTabs); } else { return FiltersView.filters[items.get(position).filterIndex].getTitle(); } @@ -962,6 +1089,8 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie public View createView(int viewType) { if (viewType == 1) { return searchContainer; + } else if (viewType == 3) { + return channelsSearchContainer; } else if (viewType == 2) { downloadsContainer = new SearchDownloadsContainer(parent, currentAccount); downloadsContainer.recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -993,6 +1122,9 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie if (items.get(position).type == DIALOGS_TYPE) { return 1; } + if (items.get(position).type == CHANNELS_TYPE) { + return 3; + } if (items.get(position).type == DOWNLOADS_TYPE) { return 2; } 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 1c2389692..9016ee5b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -1147,6 +1147,9 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi updateLayout(); previousScrollOffsetY = scrollOffsetY; } + if (Bulletin.getVisibleBulletin() != null && Bulletin.getVisibleBulletin().getLayout() != null && Bulletin.getVisibleBulletin().getLayout().getParent() instanceof View && ((View) Bulletin.getVisibleBulletin().getLayout().getParent()).getParent() == bulletinContainer2) { + Bulletin.hideVisible(); + } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java index 7bfd691de..c0218ad44 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java @@ -26,28 +26,35 @@ public class ShareLocationDrawable extends Drawable { private Drawable drawableRight; private int currentType; + public static final int TYPE_ADD = 4; + public static final int TYPE_DISABLE = 5; + public ShareLocationDrawable(Context context, int type) { currentType = type; - if (type == 4) { - drawable = context.getResources().getDrawable(R.drawable.pin); - drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright); + if (type == TYPE_ADD) { + drawable = context.getResources().getDrawable(R.drawable.filled_extend_location).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright).mutate(); + } else if (type == TYPE_DISABLE) { + drawable = context.getResources().getDrawable(R.drawable.filled_stop_location).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright).mutate(); } else if (type == 3) { - drawable = context.getResources().getDrawable(R.drawable.nearby_l); - drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.animationpinright); + drawable = context.getResources().getDrawable(R.drawable.nearby_l).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.animationpinright).mutate(); } else if (type == 2) { - drawable = context.getResources().getDrawable(R.drawable.nearby_m); - drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.animationpinright); + drawable = context.getResources().getDrawable(R.drawable.nearby_m).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.animationpinright).mutate(); } else if (type == 1) { - drawable = context.getResources().getDrawable(R.drawable.smallanimationpin); - drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright); + drawable = context.getResources().getDrawable(R.drawable.smallanimationpin).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright).mutate(); } else { - drawable = context.getResources().getDrawable(R.drawable.animationpin); - drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.animationpinright); + drawable = context.getResources().getDrawable(R.drawable.animationpin).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.animationpinright).mutate(); } } @@ -76,7 +83,7 @@ public class ShareLocationDrawable extends Drawable { int drawableW = drawable.getIntrinsicWidth(); int drawableH = drawable.getIntrinsicHeight(); - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { size = AndroidUtilities.dp(24); } else if (currentType == 3) { size = AndroidUtilities.dp(44); @@ -104,7 +111,7 @@ public class ShareLocationDrawable extends Drawable { int cx; int cx2; int cy; - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { w = AndroidUtilities.dp((2.5f) * scale); h = AndroidUtilities.dp((6.5f) * scale); tx = AndroidUtilities.dp((6.0f) * progress[a]); @@ -183,7 +190,7 @@ public class ShareLocationDrawable extends Drawable { @Override public int getIntrinsicWidth() { - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { return AndroidUtilities.dp(42); } else if (currentType == 3) { return AndroidUtilities.dp(100); @@ -197,7 +204,7 @@ public class ShareLocationDrawable extends Drawable { @Override public int getIntrinsicHeight() { - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { return AndroidUtilities.dp(42); } else if (currentType == 3) { return AndroidUtilities.dp(100); 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 09c99a7bb..fd63bd683 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -2,6 +2,7 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.lerp; +import static org.telegram.messenger.LocaleController.formatPluralString; import static org.telegram.messenger.LocaleController.getString; import static org.telegram.messenger.MediaDataController.MEDIA_PHOTOVIDEO; @@ -363,6 +364,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } public boolean isSwipeBackEnabled() { + if (canEditStories() && getClosestTab() == TAB_STORIES && isActionModeShown()) { + return false; + } return !photoVideoChangeColumnsAnimation && !tabsAnimationInProgress; } @@ -599,6 +603,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private SavedMessagesSearchAdapter savedMessagesSearchAdapter; private ChatActivityContainer savedMessagesContainer; private ChatUsersAdapter chatUsersAdapter; + private ItemTouchHelper storiesReorder; private StoriesAdapter storiesAdapter; private StoriesAdapter animationSupportingStoriesAdapter; private StoriesAdapter archivedStoriesAdapter; @@ -1420,6 +1425,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private HintView fwdRestrictedHint; private Theme.ResourcesProvider resourcesProvider; + private Runnable applyBulletin; + public boolean hasInternet() { return profileActivity.getConnectionsManager().getConnectionState() == ConnectionsManager.ConnectionStateConnected; } @@ -1931,21 +1938,23 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter actionModeViews.add(selectedMessagesCountTextView); if (!DialogObject.isEncryptedDialog(dialog_id)) { - gotoItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); - gotoItem.setIcon(R.drawable.msg_message); - gotoItem.setContentDescription(getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage)); - gotoItem.setDuplicateParentStateEnabled(false); - actionModeLayout.addView(gotoItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); - actionModeViews.add(gotoItem); - gotoItem.setOnClickListener(v -> onActionBarItemClick(v, gotochat)); + if (!isStoriesView()) { + gotoItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + gotoItem.setIcon(R.drawable.msg_message); + gotoItem.setContentDescription(getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage)); + gotoItem.setDuplicateParentStateEnabled(false); + actionModeLayout.addView(gotoItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); + actionModeViews.add(gotoItem); + gotoItem.setOnClickListener(v -> onActionBarItemClick(v, gotochat)); - forwardItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); - forwardItem.setIcon(R.drawable.msg_forward); - forwardItem.setContentDescription(getString("Forward", R.string.Forward)); - forwardItem.setDuplicateParentStateEnabled(false); - actionModeLayout.addView(forwardItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); - actionModeViews.add(forwardItem); - forwardItem.setOnClickListener(v -> onActionBarItemClick(v, forward)); + forwardItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + forwardItem.setIcon(R.drawable.msg_forward); + forwardItem.setContentDescription(getString("Forward", R.string.Forward)); + forwardItem.setDuplicateParentStateEnabled(false); + actionModeLayout.addView(forwardItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); + actionModeViews.add(forwardItem); + forwardItem.setOnClickListener(v -> onActionBarItemClick(v, forward)); + } pinItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); pinItem.setIcon(R.drawable.msg_pin); @@ -2031,6 +2040,67 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } }; + storiesReorder = new ItemTouchHelper(new ItemTouchHelper.Callback() { + private RecyclerListView listView; + @Override + public boolean isLongPressDragEnabled() { + return isActionModeShowed; + } + + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + if (isActionModeShowed && storiesAdapter.canReorder(viewHolder.getAdapterPosition())) { + listView = mediaPages[0] == null ? null : mediaPages[0].listView; + if (listView != null) { + listView.setItemAnimator(mediaPages[0].itemAnimator); + } + return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, 0); + } else { + return makeMovementFlags(0, 0); + } + } + + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + if (!storiesAdapter.canReorder(viewHolder.getAdapterPosition()) || !storiesAdapter.canReorder(target.getAdapterPosition())) { + return false; + } + storiesAdapter.swapElements(viewHolder.getAdapterPosition(), target.getAdapterPosition()); + return true; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + + } + + @Override + public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { + if (listView != null && viewHolder != null) { + listView.hideSelector(false); + } + if (actionState == ItemTouchHelper.ACTION_STATE_IDLE) { + storiesAdapter.reorderDone(); + if (listView != null) { + listView.setItemAnimator(null); + } + } else { + if (listView != null) { + listView.cancelClickRunnables(false); + } + if (viewHolder != null) { + viewHolder.itemView.setPressed(true); + } + } + super.onSelectedChanged(viewHolder, actionState); + } + + @Override + public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); + viewHolder.itemView.setPressed(false); + } + }); animationSupportingStoriesAdapter = new StoriesAdapter(context, false); archivedStoriesAdapter = new StoriesAdapter(context, true) { @Override @@ -2097,7 +2167,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter invalidateBlur(); } }; - addView(mediaPage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, isStoriesView() ? 0 : 48, 0, 0)); + addView(mediaPage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, customTabs() ? 0 : 48, 0, 0)); if (a == 1) { mediaPage.setTranslationX(AndroidUtilities.displaySize.x); } @@ -2207,7 +2277,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mediaPages[a].buttonView.setOnClickListener(v -> { if (v.getAlpha() < 0.5f) return; profileActivity.getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); - StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); + openStoryRecorder(); }); mediaPages[a].listView = new InternalListView(context) { @@ -2593,6 +2663,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter poller = UserListPoller.getInstance(profileActivity.getCurrentAccount()); } poller.checkList(this); + + if (!photoVideoChangeColumnsAnimation) { + changeColumnsTab = -1; + } } @Override @@ -2929,7 +3003,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter return onItemLongClick(((SharedAudioCell) view).getMessage(), view, 0); } else if (mediaPage.selectedType == TAB_GIF && view instanceof ContextLinkCell) { return onItemLongClick((MessageObject) ((ContextLinkCell) view).getParentObject(), view, 0); - } else if ((mediaPage.selectedType == TAB_PHOTOVIDEO || mediaPage.selectedType == TAB_ARCHIVED_STORIES || mediaPage.selectedType == TAB_STORIES && isStoriesView()) && view instanceof SharedPhotoVideoCell2) { + } else if ((mediaPage.selectedType == TAB_PHOTOVIDEO || mediaPage.selectedType == TAB_ARCHIVED_STORIES || mediaPage.selectedType == TAB_STORIES && canEditStories()) && view instanceof SharedPhotoVideoCell2) { MessageObject messageObject = ((SharedPhotoVideoCell2) view).getMessageObject(); if (messageObject != null) { return onItemLongClick(messageObject, view, mediaPage.selectedType); @@ -3042,7 +3116,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter floatingDateView.setTranslationY(-dp(48)); addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 48 + 4, 0, 0)); - if (!isStoriesView()) { + if (!customTabs()) { addView(fragmentContextView = new FragmentContextView(context, parent, this, false, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); fragmentContextView.setDelegate((start, show) -> { if (!start) { @@ -3101,7 +3175,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter shadowLine = new View(context); shadowLine.setBackgroundColor(getThemedColor(Theme.key_divider)); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1); - layoutParams.topMargin = isStoriesView() ? 0 : dp(48) - 1; + layoutParams.topMargin = customTabs() ? 0 : dp(48) - 1; addView(shadowLine, layoutParams); updateTabs(false); @@ -3111,6 +3185,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } + protected boolean customTabs() { + return false; + } + protected boolean isStoriesView() { return false; } @@ -3127,6 +3205,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter return false; } + protected boolean isSelf() { + return false; + } + protected int getInitialTab() { return 0; } @@ -3367,9 +3449,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : (changeColumnsTab == TAB_STORIES && isStoriesView() ? dp(72) : 0), + changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0, mediaPage.animationSupportingListView.getPaddingRight(), - mediaPage.animationSupportingListView.getPaddingBottom() + isStoriesView() ? dp(72) : 0 ); mediaPage.buttonView.setVisibility(changeColumnsTab == TAB_STORIES && isStoriesView() ? View.VISIBLE : View.GONE); @@ -3569,9 +3651,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : (changeColumnsTab == TAB_STORIES && isStoriesView() ? dp(72) : 0))), + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0)), mediaPage.animationSupportingListView.getPaddingRight(), - mediaPage.animationSupportingListView.getPaddingBottom() + (mediaPage.animationSupportingListView.hintPaddingBottom = (isStoriesView() ? dp(72) : 0)) ); mediaPage.buttonView.setVisibility(changeColumnsTab == TAB_STORIES ? View.VISIBLE : View.GONE); mediaPage.buttonView.setVisibility(changeColumnsTab == TAB_STORIES ? View.VISIBLE : View.GONE); @@ -3613,7 +3695,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter continue; } int oldItemCount = adapter.getItemCount(); - if (i == TAB_PHOTOVIDEO) { + if (i == 0) { sharedMediaData[0].setListFrozen(false); } mediaPages[i].layoutManager.setSpanCount(mediaColumnsCount[ci]); @@ -4245,7 +4327,38 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public void onActionBarItemClick(View v, int id) { if (id == delete) { - if (getSelectedTab() == TAB_SAVED_DIALOGS) { + if (getSelectedTab() == TAB_STORIES || getSelectedTab() == TAB_ARCHIVED_STORIES) { + if (selectedFiles[0] != null) { + ArrayList storyItems = new ArrayList<>(); + for (int i = 0; i < selectedFiles[0].size(); ++i) { + MessageObject messageObject = selectedFiles[0].valueAt(i); + if (messageObject.storyItem != null) { + storyItems.add(messageObject.storyItem); + } + } + + if (!storyItems.isEmpty()) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourcesProvider); + builder.setTitle(storyItems.size() > 1 ? LocaleController.getString(R.string.DeleteStoriesTitle) : LocaleController.getString(R.string.DeleteStoryTitle)); + builder.setMessage(LocaleController.formatPluralString("DeleteStoriesSubtitle", storyItems.size())); + builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + profileActivity.getMessagesController().getStoriesController().deleteStories(dialog_id, storyItems); + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.ic_delete, LocaleController.formatPluralString("StoriesDeleted", storyItems.size())).show(); + closeActionMode(false); + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.redPositive(); + } + } + return; + } else if (getSelectedTab() == TAB_SAVED_DIALOGS) { final SavedMessagesController controller = profileActivity.getMessagesController().getSavedMessagesController(); final ArrayList selectedDialogs = new ArrayList<>(); for (int i = 0; i < controller.allDialogs.size(); ++i) { @@ -4304,7 +4417,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else { currentChat = profileActivity.getMessagesController().getChat(-dialog_id); } - AlertsCreator.createDeleteMessagesAlert(profileActivity, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, 0, 0, 1, () -> { + AlertsCreator.createDeleteMessagesAlert(profileActivity, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, 0, 0, null, () -> { showActionMode(false); actionBar.closeSearchField(); cantDeleteMessagesCount = 0; @@ -4432,26 +4545,112 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } profileActivity.presentFragment(chatActivity, false); } else if (id == pin || id == unpin) { - final SavedMessagesController controller = profileActivity.getMessagesController().getSavedMessagesController(); - final ArrayList selectedDialogs = new ArrayList<>(); - for (int i = 0; i < controller.allDialogs.size(); ++i) { - final long did = controller.allDialogs.get(i).dialogId; - if (savedDialogsAdapter.selectedDialogs.contains(did)) { - selectedDialogs.add(did); + if (getClosestTab() == TAB_STORIES) { + if (storiesAdapter == null || storiesAdapter.storiesList == null) + return; + ArrayList ids = new ArrayList<>(); + for (int i = 0; i < selectedFiles[0].size(); ++i) { + ids.add(selectedFiles[0].valueAt(i).getId()); } - } - if (!controller.updatePinned(selectedDialogs, id == pin, true)) { - LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(profileActivity, getContext(), LimitReachedBottomSheet.TYPE_PIN_SAVED_DIALOGS, profileActivity.getCurrentAccount(), null); - profileActivity.showDialog(limitReachedBottomSheet); + if (id == pin && ids.size() > profileActivity.getMessagesController().storiesPinnedToTopCountMax) { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.chats_infotip, AndroidUtilities.replaceTags(formatPluralString("StoriesPinLimit", profileActivity.getMessagesController().storiesPinnedToTopCountMax))).show(); + return; + } + + if (storiesAdapter.storiesList.updatePinned(ids, id == pin)) { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.chats_infotip, AndroidUtilities.replaceTags(formatPluralString("StoriesPinLimit", profileActivity.getMessagesController().storiesPinnedToTopCountMax))).show(); + } else { + if (id == pin) { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.ic_pin, AndroidUtilities.replaceTags(formatPluralString("StoriesPinned", ids.size())), formatPluralString("StoriesPinnedText", ids.size())).show(); + } else { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.ic_unpin, AndroidUtilities.replaceTags(formatPluralString("StoriesUnpinned", ids.size()))).show(); + } + + } + + closeActionMode(false); +// if (profileActivity == null) return; +// final long dialogId = profileActivity.getUserConfig().getClientUserId(); +// if (applyBulletin != null) { +// applyBulletin.run(); +// applyBulletin = null; +// } +// Bulletin.hideVisible(); +// boolean pin = getClosestTab() == SharedMediaLayout.TAB_ARCHIVED_STORIES; +// int count = 0; +// ArrayList storyItems = new ArrayList<>(); +// SparseArray actionModeMessageObjects = getActionModeSelected(); +// if (actionModeMessageObjects != null) { +// for (int i = 0; i < actionModeMessageObjects.size(); ++i) { +// MessageObject messageObject = actionModeMessageObjects.valueAt(i); +// if (messageObject.storyItem != null) { +// storyItems.add(messageObject.storyItem); +// count++; +// } +// } +// } +// closeActionMode(false); +// if (pin) { +// scrollToPage(SharedMediaLayout.TAB_STORIES); +// scrollSlidingTextTabStrip.selectTabWithId(SharedMediaLayout.TAB_STORIES, 1f); +// } +// if (storyItems.isEmpty()) { +// return; +// } +// boolean[] pastValues = new boolean[storyItems.size()]; +// for (int i = 0; i < storyItems.size(); ++i) { +// TL_stories.StoryItem storyItem = storyItems.get(i); +// pastValues[i] = storyItem.pinned; +// storyItem.pinned = pin; +// } +// profileActivity.getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); +// final boolean[] undone = new boolean[] { false }; +// applyBulletin = () -> { +// profileActivity.getMessagesController().getStoriesController().updateStoriesPinned(dialogId, storyItems, pin, null); +// }; +// final Runnable undo = () -> { +// undone[0] = true; +// AndroidUtilities.cancelRunOnUIThread(applyBulletin); +// for (int i = 0; i < storyItems.size(); ++i) { +// TL_stories.StoryItem storyItem = storyItems.get(i); +// storyItem.pinned = pastValues[i]; +// } +// profileActivity.getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); +// }; +// Bulletin bulletin; +// if (pin) { +// bulletin = BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.contact_check, LocaleController.formatPluralString("StorySavedTitle", count), LocaleController.getString(R.string.StorySavedSubtitle), LocaleController.getString(R.string.Undo), undo).show(); +// } else { +// bulletin = BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.chats_archived, LocaleController.formatPluralString("StoryArchived", count), LocaleController.getString(R.string.Undo), Bulletin.DURATION_PROLONG, undo).show(); +// } +// bulletin.setOnHideListener(() -> { +// if (!undone[0] && applyBulletin != null) { +// applyBulletin.run(); +// } +// applyBulletin = null; +// }); } else { - for (int i = 0; i < mediaPages.length; ++i) { - if (mediaPages[i].selectedType == TAB_SAVED_DIALOGS) { - mediaPages[i].layoutManager.scrollToPositionWithOffset(0, 0); - break; + final SavedMessagesController controller = profileActivity.getMessagesController().getSavedMessagesController(); + final ArrayList selectedDialogs = new ArrayList<>(); + for (int i = 0; i < controller.allDialogs.size(); ++i) { + final long did = controller.allDialogs.get(i).dialogId; + if (savedDialogsAdapter.selectedDialogs.contains(did)) { + selectedDialogs.add(did); } } + if (!controller.updatePinned(selectedDialogs, id == pin, true)) { + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(profileActivity, getContext(), LimitReachedBottomSheet.TYPE_PIN_SAVED_DIALOGS, profileActivity.getCurrentAccount(), null); + profileActivity.showDialog(limitReachedBottomSheet); + } else { + for (int i = 0; i < mediaPages.length; ++i) { + if (mediaPages[i].selectedType == TAB_SAVED_DIALOGS) { + mediaPages[i].layoutManager.scrollToPositionWithOffset(0, 0); + break; + } + } + } + closeActionMode(true); } - closeActionMode(true); } } @@ -4470,6 +4669,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (searching && getSelectedTab() == TAB_SAVED_DIALOGS) { return false; } + if (canEditStories() && isActionModeShowed && getClosestTab() == TAB_STORIES) { + return false; + } updateOptionsSearch(); getParent().requestDisallowInterceptTouchEvent(true); @@ -4532,7 +4734,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } if (child instanceof MediaPage) { measureChildWithMargins(child, widthMeasureSpec, 0, MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY), 0); - ((MediaPage) child).listView.setPadding(0, ((MediaPage) child).listView.topPadding, 0, topPadding); + ((MediaPage) child).listView.setPadding(0, ((MediaPage) child).listView.topPadding, 0, ((MediaPage) child).listView.bottomPadding); } else { measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); } @@ -4803,6 +5005,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter selectedFiles[a].clear(); } cantDeleteMessagesCount = 0; + onActionModeSelectedUpdate(selectedFiles[0]); showActionMode(false); updateRowsSelection(uncheckAnimated); if (savedDialogsAdapter != null) { @@ -4827,6 +5030,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } + public SparseArray getActionModeSelected() { + return selectedFiles[0]; + } + private AnimatorSet actionModeAnimation; public boolean isActionModeShown() { @@ -4865,6 +5072,35 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } }); actionModeAnimation.start(); + if (show) { + updateStoriesPinButton(); + } + } + + private void updateStoriesPinButton() { + if (getClosestTab() == TAB_ARCHIVED_STORIES) { + if (pinItem != null) { + pinItem.setVisibility(View.GONE); + } + if (unpinItem != null) { + unpinItem.setVisibility(View.GONE); + } + } else if (getClosestTab() == TAB_STORIES) { + boolean hasUnpinned = false; + for (int i = 0; i < selectedFiles[0].size(); ++i) { + MessageObject msg = selectedFiles[0].valueAt(i); + if (storiesAdapter != null && storiesAdapter.storiesList != null && !storiesAdapter.storiesList.isPinned(msg.getId())) { + hasUnpinned = true; + break; + } + } + if (pinItem != null) { + pinItem.setVisibility(hasUnpinned ? View.VISIBLE : View.GONE); + } + if (unpinItem != null) { + unpinItem.setVisibility(!hasUnpinned ? View.VISIBLE : View.GONE); + } + } } @Override @@ -5639,16 +5875,16 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if ((DialogObject.isUserDialog(dialog_id) || DialogObject.isChatDialog(dialog_id)) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || info != null && info.stories_pinned_available || isStoriesView()) && includeStories()) { if (isArchivedOnlyStoriesView()) { if (!scrollSlidingTextTabStrip.hasTab(TAB_ARCHIVED_STORIES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString("ProfileStories", R.string.ProfileStories), idToView); + scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString(R.string.ProfileArchivedStories), idToView); } scrollSlidingTextTabStrip.animationDuration = 420; } else { if (!scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, getString("ProfileStories", R.string.ProfileStories), idToView); + scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, getString(R.string.ProfileStories), idToView); } if (isStoriesView()) { if (!scrollSlidingTextTabStrip.hasTab(TAB_ARCHIVED_STORIES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString("ProfileStories", R.string.ProfileStories), idToView); + scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString(R.string.ProfileArchivedStories), idToView); } scrollSlidingTextTabStrip.animationDuration = 420; } @@ -5763,6 +5999,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter boolean fastScrollVisible = false; int spanCount = 100; RecyclerView.Adapter currentAdapter = mediaPages[a].listView.getAdapter(); + if (currentAdapter == storiesAdapter) { + storiesReorder.attachToRecyclerView(null); + } RecyclerView.RecycledViewPool viewPool = null; if (searching && searchWas) { if (mediaPages[a].searchViewPool == null) { @@ -5865,9 +6104,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mediaPages[a].listView.setPinnedHeaderShadowDrawable(null); mediaPages[a].listView.setPadding( mediaPages[a].listView.getPaddingLeft(), - (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : (mediaPages[a].selectedType == TAB_STORIES && isStoriesView() ? dp(72) : 0)), + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : 0), mediaPages[a].listView.getPaddingRight(), - mediaPages[a].listView.getPaddingBottom() + (mediaPages[a].listView.hintPaddingTop = isStoriesView() ? dp(72) : 0) ); mediaPages[a].buttonView.setVisibility(mediaPages[a].selectedType == TAB_STORIES && isStoriesView() ? View.VISIBLE : View.GONE); @@ -5935,6 +6174,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(storiesAdapter); } + storiesReorder.attachToRecyclerView(mediaPages[a].listView); spanCount = mediaColumnsCount[1]; } else if (mediaPages[a].selectedType == TAB_ARCHIVED_STORIES) { if (currentAdapter != archivedStoriesAdapter) { @@ -6050,26 +6290,39 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } if (mediaPages[a].selectedType == TAB_STORIES) { - mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + if (isSelf()) { + mediaPages[a].emptyView.stickerView.setVisibility(View.GONE); + mediaPages[a].emptyView.button.setVisibility(View.GONE); + } else { + mediaPages[a].emptyView.stickerView.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.button.setText(addPostText(), false); + } mediaPages[a].emptyView.title.setText(isStoriesView() ? getString(R.string.NoPublicStoriesTitle2) : getString(R.string.NoStoriesTitle)); mediaPages[a].emptyView.subtitle.setText(isStoriesView() ? getString(R.string.NoStoriesSubtitle2) : ""); - mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); - mediaPages[a].emptyView.button.setText(addPostText(), false); mediaPages[a].emptyView.button.setOnClickListener(v -> { profileActivity.getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); }); } else if (mediaPages[a].selectedType == TAB_ARCHIVED_STORIES) { - mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + if (isSelf()) { + mediaPages[a].emptyView.stickerView.setVisibility(View.GONE); + mediaPages[a].emptyView.button.setVisibility(View.GONE); + } else { + mediaPages[a].emptyView.stickerView.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.button.setText(addPostText(), false); + } mediaPages[a].emptyView.title.setText(getString(R.string.NoArchivedStoriesTitle)); mediaPages[a].emptyView.subtitle.setText(isStoriesView() ? getString(R.string.NoArchivedStoriesSubtitle) : ""); - mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); - mediaPages[a].emptyView.button.setText(addPostText(), false); mediaPages[a].emptyView.button.setOnClickListener(v -> { profileActivity.getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); }); } else { + mediaPages[a].emptyView.stickerView.setVisibility(View.VISIBLE); mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_SEARCH); mediaPages[a].emptyView.title.setText(getString("NoResult", R.string.NoResult)); mediaPages[a].emptyView.subtitle.setText(getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2)); @@ -6107,7 +6360,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } deleteItem.setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); if (gotoItem != null) { - gotoItem.setVisibility(View.VISIBLE); + gotoItem.setVisibility(getClosestTab() != TAB_STORIES ? View.VISIBLE : View.GONE); + } + if (forwardItem != null) { + forwardItem.setVisibility(getClosestTab() != TAB_STORIES ? View.VISIBLE : View.GONE); } selectedMessagesCountTextView.setNumber(1, false); AnimatorSet animatorSet = new AnimatorSet(); @@ -6147,7 +6403,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter return; } if (isActionModeShowed) { - if (selectedMode == TAB_STORIES && !isStoriesView()) { + if (selectedMode == TAB_STORIES && !canEditStories()) { return; } int loadIndex = message.getDialogId() == dialog_id ? 0 : 1; @@ -6172,17 +6428,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter selectedMessagesCountTextView.setNumber(selectedFiles[0].size() + selectedFiles[1].size(), true); deleteItem.setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); if (gotoItem != null) { - gotoItem.setVisibility(selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); + gotoItem.setVisibility(getClosestTab() != TAB_STORIES && selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); } if (forwardItem != null) { - forwardItem.setVisibility(View.VISIBLE); - } - if (pinItem != null) { - pinItem.setVisibility(View.GONE); - } - if (unpinItem != null) { - unpinItem.setVisibility(View.GONE); + forwardItem.setVisibility(getClosestTab() != TAB_STORIES ? View.VISIBLE : View.GONE); } + updateStoriesPinButton(); } scrolling = false; if (view instanceof SharedDocumentCell) { @@ -6199,13 +6450,13 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter ((SharedPhotoVideoCell2) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); } } else { - if (selectedMode == 0) { + if (selectedMode == TAB_PHOTOVIDEO) { int i = index - sharedMediaData[selectedMode].startOffset; if (i >= 0 && i < sharedMediaData[selectedMode].messages.size()) { PhotoViewer.getInstance().setParentActivity(profileActivity); PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, i, dialog_id, mergeDialogId, topicId, provider); } - } else if (selectedMode == 2 || selectedMode == 4) { + } else if (selectedMode == TAB_VOICE || selectedMode == TAB_AUDIO) { if (view instanceof SharedAudioCell) { ((SharedAudioCell) view).didPressedButton(); } @@ -6219,7 +6470,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } else { PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, index, dialog_id, mergeDialogId, topicId, provider); } - } else if (selectedMode == 1) { + } else if (selectedMode == TAB_FILES) { if (view instanceof SharedDocumentCell) { SharedDocumentCell cell = (SharedDocumentCell) view; TLRPC.Document document = message.getDocument(); @@ -6247,7 +6498,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter cell.updateFileExistIcon(true); } } - } else if (selectedMode == 3) { + } else if (selectedMode == TAB_LINKS) { try { TLRPC.WebPage webPage = MessageObject.getMedia(message.messageOwner) != null ? MessageObject.getMedia(message.messageOwner).webpage : null; String link = null; @@ -6913,7 +7164,28 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (sharedResources == null) { sharedResources = new SharedPhotoVideoCell2.SharedResources(parent.getContext(), resourcesProvider); } - SharedPhotoVideoCell2 cell = new SharedPhotoVideoCell2(mContext, sharedResources, profileActivity.getCurrentAccount()); + SharedPhotoVideoCell2 cell = new SharedPhotoVideoCell2(mContext, sharedResources, profileActivity.getCurrentAccount()) { +// private Runnable startDragRunnable = () -> { +// if (mediaPages[0] == null || mediaPages[0].listView == null) { +// return; +// } +// if (isActionModeShowed && viewType == VIEW_TYPE_STORY && SharedPhotoVideoAdapter.this == storiesAdapter && isStoriesView()) { +// storiesReorder.startDrag(mediaPages[0].listView.getChildViewHolder(this)); +// } +// }; +// @Override +// public boolean onTouchEvent(MotionEvent event) { +// if (isActionModeShowed && viewType == VIEW_TYPE_STORY && SharedPhotoVideoAdapter.this == storiesAdapter && isStoriesView()) { +// if (event.getAction() == MotionEvent.ACTION_DOWN) { +// AndroidUtilities.cancelRunOnUIThread(this.startDragRunnable); +// AndroidUtilities.runOnUIThread(this.startDragRunnable, (long) (ViewConfiguration.getLongPressTimeout() * .75f)); +// } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) { +// AndroidUtilities.cancelRunOnUIThread(this.startDragRunnable); +// } +// } +// return super.onTouchEvent(event); +// } + }; cell.setGradientView(globalGradientView); if (this == storiesAdapter || this == archivedStoriesAdapter) { cell.isStory = true; @@ -8136,7 +8408,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } profileActivity.getNotificationCenter().postNotificationName(NotificationCenter.channelRecommendationsLoaded, -dialog_id); profileActivity.getMessagesController().addUserToChat(chat.id, profileActivity.getUserConfig().getCurrentUser(), 0, null, profileActivity, () -> { - BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.contact_check, LocaleController.formatString(R.string.YouJoinedChannel, chat == null ? "" : chat.title)).show(); + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.contact_check, LocaleController.formatString(R.string.YouJoinedChannel, chat == null ? "" : chat.title)).show(true); }); }); previewMenu.addView(joinChannel); @@ -8544,11 +8816,13 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter cell.isStory = true; position -= getTopOffset(); if (position < 0 || position >= storiesList.messageObjects.size()) { + cell.isStoryPinned = false; cell.setMessageObject(null, columnsCount()); cell.isStory = true; return; } MessageObject messageObject = storiesList.messageObjects.get(position); + cell.isStoryPinned = messageObject != null && storiesList.isPinned(messageObject.getId()); cell.setMessageObject(messageObject, columnsCount()); if (isActionModeShowed && messageObject != null) { cell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, false); @@ -8593,6 +8867,66 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public void onFastScrollSingleTap() { showMediaCalendar(isArchive ? TAB_ARCHIVED_STORIES : TAB_STORIES, true); } + + public boolean canReorder(int position) { + if (isArchive) return false; + if (storiesList == null) return false; + if (position < 0 || position >= storiesList.messageObjects.size()) return false; + MessageObject messageObject = storiesList.messageObjects.get(position); + return storiesList.isPinned(messageObject.getId()); + } + + public ArrayList lastPinnedIds = new ArrayList<>(); + public boolean applyingReorder; + + public boolean swapElements(int fromPosition, int toPosition) { + if (isArchive) return false; + if (storiesList == null) return false; + if (fromPosition < 0 || fromPosition >= storiesList.messageObjects.size()) return false; + if (toPosition < 0 || toPosition >= storiesList.messageObjects.size()) return false; + + ArrayList pinnedIds = new ArrayList<>(storiesList.pinnedIds); + + if (!applyingReorder) { + lastPinnedIds.clear(); + lastPinnedIds.addAll(pinnedIds); + applyingReorder = true; + } + + MessageObject from = storiesList.messageObjects.get(fromPosition); + MessageObject to = storiesList.messageObjects.get(toPosition); + + pinnedIds.remove((Object) from.getId()); + pinnedIds.add(Utilities.clamp(toPosition, pinnedIds.size(), 0), from.getId()); + + storiesList.updatePinnedOrder(pinnedIds, false); + + notifyItemMoved(fromPosition, toPosition); + + return true; + } + + public void reorderDone() { + if (isArchive) return; + if (storiesList == null) return; + if (!applyingReorder) return; + + boolean changed = lastPinnedIds.size() != storiesList.pinnedIds.size(); + if (!changed) { + for (int i = 0; i < lastPinnedIds.size(); ++i) { + if (lastPinnedIds.get(i) != storiesList.pinnedIds.get(i)) { + changed = true; + break; + } + } + } + + if (changed) { + storiesList.updatePinnedOrder(storiesList.pinnedIds, true); + } + + applyingReorder = false; + } } private class ChatUsersAdapter extends RecyclerListView.SelectionAdapter { @@ -9247,6 +9581,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public static class InternalListView extends BlurredRecyclerView implements StoriesListPlaceProvider.ClippedView { public int hintPaddingTop; + public int hintPaddingBottom; public InternalListView(Context context) { super(context); @@ -9255,7 +9590,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public void updateClip(int[] clip) { clip[0] = getPaddingTop() - dp(2) - hintPaddingTop; - clip[1] = getMeasuredHeight() - getPaddingBottom(); + clip[1] = getMeasuredHeight() - getPaddingBottom() - hintPaddingBottom; } } @@ -9333,4 +9668,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter }), boldN) ).setDuration(8000).show(true); } + + public boolean canEditStories() { + return isStoriesView() || profileActivity != null && profileActivity.getMessagesController().getStoriesController().canEditStories(dialog_id); + } + + public void openStoryRecorder() { + StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java index c96108db1..546c1a5b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java @@ -62,6 +62,7 @@ public class SharingLocationsAlert extends BottomSheet implements NotificationCe super(context, false, resourcesProvider); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.liveLocationsChanged); delegate = sharingLocationsAlertDelegate; + fixNavigationBar(); shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java index 8dd08be9c..d4b2dad5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java @@ -63,4 +63,8 @@ public class SlideView extends LinearLayout { public boolean needBackButton() { return false; } + + public void onResume() { + + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java index caf86c1ed..a37349a5b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java @@ -50,12 +50,18 @@ import java.util.Set; public class StickerCategoriesListView extends RecyclerListView { - @IntDef({CategoriesType.DEFAULT, CategoriesType.STATUS, CategoriesType.PROFILE_PHOTOS}) + @IntDef({ + CategoriesType.DEFAULT, + CategoriesType.STATUS, + CategoriesType.PROFILE_PHOTOS, + CategoriesType.STICKERS + }) @Retention(RetentionPolicy.SOURCE) public static @interface CategoriesType { int DEFAULT = 0; int STATUS = 1; int PROFILE_PHOTOS = 2; + int STICKERS = 3; } private float shownButtonsAtStart = 6.5f; @@ -98,7 +104,7 @@ public class StickerCategoriesListView extends RecyclerListView { if (emojiGroups == null || emojiGroups.groups == null) { return; } - for (TLRPC.TL_emojiGroup group : emojiGroups.groups) { + for (TLRPC.EmojiGroup group : emojiGroups.groups) { AnimatedEmojiDrawable.getDocumentFetcher(account).fetchDocument(group.icon_emoji_id, null); } }); @@ -150,6 +156,7 @@ public class StickerCategoriesListView extends RecyclerListView { for (int j = 0; j < emojiGroups.groups.size(); ++j) { categories[i + j] = EmojiCategory.remote(emojiGroups.groups.get(j)); } + categories = preprocessCategories(categories); adapter.notifyDataSetChanged(); setCategoriesShownT(0); updateCategoriesShown(categoriesShouldShow, System.currentTimeMillis() - start > 16); @@ -159,6 +166,10 @@ public class StickerCategoriesListView extends RecyclerListView { }); } + protected EmojiCategory[] preprocessCategories(StickerCategoriesListView.EmojiCategory[] categories) { + return categories; + } + public void setShownButtonsAtStart(float buttonsCount) { shownButtonsAtStart = buttonsCount; } @@ -832,6 +843,8 @@ public class StickerCategoriesListView extends RecyclerListView { public boolean animated; public int iconResId; public String emojis; + public boolean premium; + public boolean greeting; public boolean remote; public long documentId; @@ -854,11 +867,17 @@ public class StickerCategoriesListView extends RecyclerListView { return category; } - public static EmojiCategory remote(TLRPC.TL_emojiGroup group) { + public static EmojiCategory remote(TLRPC.EmojiGroup group) { EmojiCategory category = new EmojiCategory(); category.remote = true; category.documentId = group.icon_emoji_id; - category.emojis = TextUtils.concat(group.emoticons.toArray(new String[0])).toString(); + if (group instanceof TLRPC.TL_emojiGroupPremium) { + category.emojis = "premium"; + category.premium = true; + } else { + category.emojis = TextUtils.concat(group.emoticons.toArray(new String[0])).toString(); + } + category.greeting = group instanceof TLRPC.TL_emojiGroupGreeting; category.title = group.title; return category; } @@ -875,6 +894,9 @@ public class StickerCategoriesListView extends RecyclerListView { } else if (type == CategoriesType.PROFILE_PHOTOS) { req = new TLRPC.TL_messages_getEmojiProfilePhotoGroups(); ((TLRPC.TL_messages_getEmojiProfilePhotoGroups) req).hash = (int) hash; + } else if (type == CategoriesType.STICKERS) { + req = new TLRPC.TL_messages_getEmojiStickerGroups(); + ((TLRPC.TL_messages_getEmojiStickerGroups) req).hash = (int) hash; } else { req = new TLRPC.TL_messages_getEmojiGroups(); ((TLRPC.TL_messages_getEmojiGroups) req).hash = (int) hash; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java new file mode 100644 index 000000000..91edaded6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java @@ -0,0 +1,137 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.openDocument; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LiteMode; +import org.telegram.messenger.MessageObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + +public class StickerSetLinkIcon extends Drawable { + + private final int N, count; + private final AnimatedEmojiDrawable[] drawables; + public int alpha = 0xFF; + public final boolean out; + + public StickerSetLinkIcon(int currentAccount, boolean out, ArrayList documents, boolean text_color) { + this.out = out; + N = (int) Math.max(1, Math.sqrt(documents.size())); + count = Math.min(N * N, documents.size()); + drawables = new AnimatedEmojiDrawable[count]; + final boolean emoji = !documents.isEmpty() && MessageObject.isAnimatedEmoji(documents.get(0)); + final int cacheType = N < 2 ? AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES_LARGE : AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; + for (int i = 0; i < count; ++i) { + drawables[i] = AnimatedEmojiDrawable.make(currentAccount, cacheType, documents.get(i)); + } + } + + public boolean equals(ArrayList documents) { + if (documents == null) + return drawables.length == 0; + if (drawables.length != documents.size()) + return false; + for (int i = 0; i < drawables.length; ++i) { + TLRPC.Document d = drawables[i].getDocument(); + if ((d == null ? 0 : d.id) != documents.get(i).id) { + return false; + } + } + return true; + } + + public void attach(View parentView) { + for (int i = 0; i < count; ++i) { + drawables[i].addView(parentView); + } + } + + public void detach(View parentView) { + for (int i = 0; i < count; ++i) { + drawables[i].removeView(parentView); + } + } + + private final RectF rect = new RectF(); + @Override + public void draw(@NonNull Canvas canvas) { + if (alpha <= 0) return; + rect.set(getBounds()); + final float left = rect.centerX() - getIntrinsicWidth() / 2f; + final float top = rect.centerY() - getIntrinsicHeight() / 2f; + final float iw = getIntrinsicWidth() / N; + final float ih = getIntrinsicHeight() / N; + canvas.save(); + canvas.clipRect(left, top, left + getIntrinsicWidth(), top + getIntrinsicHeight()); + for (int y = 0; y < N; ++y) { + for (int x = 0; x < N; ++x) { + int i = x + y * N; + if (i < 0 || i >= drawables.length) continue; + if (drawables[i] == null) continue; + drawables[i].setBounds( + (int) (left + iw * x), + (int) (top + ih * y), + (int) (left + iw * (x + 1)), + (int) (top + ih * (y + 1)) + ); + drawables[i].setAlpha(alpha); + drawables[i].setColorFilter(out ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); + drawables[i].draw(canvas); + } + } + canvas.restore(); + } + + @Override + public void setAlpha(int alpha) { + this.alpha = alpha; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getIntrinsicHeight() { + return dp(48); + } + + @Override + public int getIntrinsicWidth() { + return dp(48); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + private boolean hit = false; + public void readyToDie() { + hit = true; + } + + public void keepAlive() { + hit = false; + } + + public boolean die() { + return hit; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index f06e75624..c9d6625b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -18,6 +18,7 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; @@ -37,6 +38,7 @@ import android.text.TextWatcher; import android.transition.Transition; import android.transition.TransitionManager; import android.transition.TransitionValues; +import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; @@ -72,8 +74,10 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; @@ -97,8 +101,11 @@ import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stories.DarkThemeResourceProvider; +import org.telegram.ui.Stories.recorder.StoryEntry; import java.io.File; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -107,7 +114,8 @@ import java.util.regex.Pattern; public class StickersAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { - public final static boolean DISABLE_STICKER_EDITOR = !BuildVars.DEBUG_PRIVATE_VERSION; + public final static boolean DISABLE_STICKER_EDITOR = false; + public final static int STICKERS_MAX_COUNT = 120; public interface StickersAlertDelegate { void onStickerSelected(TLRPC.Document sticker, String query, Object parent, MessageObject.SendAnimationData sendAnimationData, boolean clearsInputField, boolean notify, int scheduleDate); @@ -158,7 +166,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not public boolean probablyEmojis; private boolean isEditModeEnabled; - private TLRPC.TL_messages_stickerSet stickerSet; + public TLRPC.TL_messages_stickerSet stickerSet; private TLRPC.Document selectedSticker; private SendMessagesHelper.ImportingSticker selectedStickerPath; private TLRPC.InputStickerSet inputStickerSet; @@ -223,16 +231,34 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not removeSticker(importingSticker); } + @Override + public boolean canDeleteSticker(TLRPC.Document document) { + return true; + } + @Override public void deleteSticker(TLRPC.Document document) { stickerSet.documents.remove(document); + boolean empty = stickerSet.documents.isEmpty(); + if (empty) + dismiss(); adapter.notifyDataSetChanged(); + AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER, resourcesProvider); + progressDialog.showDelayed(350); TLRPC.TL_stickers_removeStickerFromSet req = new TLRPC.TL_stickers_removeStickerFromSet(); req.sticker = MediaDataController.getInputStickerSetItem(document, "").document; - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 2, null, false, false); + MediaDataController.getInstance(UserConfig.selectedAccount).putStickerSet((TLRPC.TL_messages_stickerSet) response); + if (empty) { + MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 0, null, false, false); + } else { + stickerSet = (TLRPC.TL_messages_stickerSet) response; + loadStickerSet(); + updateFields(); + } } + progressDialog.dismiss(); })); } @@ -249,24 +275,103 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } else { chatActivity = null; } - final ArrayList photos = new ArrayList<>(); - File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); - if (file == null || !file.exists()) { - return; - } - AndroidUtilities.runOnUIThread(() -> { - final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); - photos.add(entry); - PhotoViewer.getInstance().setParentActivity(parentFragment.getParentActivity(), resourcesProvider); - PhotoViewer.getInstance().openPhotoForSelect(photos, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { - @Override - public boolean allowCaption() { - return false; + if (MessageObject.isStaticStickerDocument(document)) { + final ArrayList photos = new ArrayList<>(); + File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); + if (file == null || !file.exists()) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); + photos.add(entry); + PhotoViewer.getInstance().setParentActivity(parentFragment.getParentActivity(), resourcesProvider); + PhotoViewer.getInstance().openPhotoForSelect(photos, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public boolean allowCaption() { + return false; + } + }, chatActivity); + PhotoViewer.getInstance().enableStickerMode(document, false, null); + ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(stickerSet); + }, 300); + } else { + AndroidUtilities.runOnUIThread(() -> { + File file = StoryEntry.makeCacheFile(currentAccount, "webp"); + int w = 512, h = 512; + int maxSide; + switch (SharedConfig.getDevicePerformanceClass()) { + case SharedConfig.PERFORMANCE_CLASS_LOW: + maxSide = 1280; + break; + default: + case SharedConfig.PERFORMANCE_CLASS_AVERAGE: + maxSide = 2560; + break; + case SharedConfig.PERFORMANCE_CLASS_HIGH: + maxSide = 3840; + break; } - }, chatActivity); - PhotoViewer.getInstance().enableStickerMode(document); - ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(stickerSet); - }, 300); + Size size = new Size(w, h); + size.width = maxSide; + size.height = (float) Math.floor(size.width * h / w); + if (size.height > maxSide) { + size.height = maxSide; + size.width = (float) Math.floor(size.height * w / h); + } + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + try { + b.compress(Bitmap.CompressFormat.WEBP, 100, new FileOutputStream(file)); + } catch (Throwable e) { + FileLog.e(e); + } + b.recycle(); + + ArrayList arrayList = new ArrayList<>(); + final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); + arrayList.add(entry); + VideoEditedInfo.MediaEntity entity = new VideoEditedInfo.MediaEntity(); + entity.type = VideoEditedInfo.MediaEntity.TYPE_STICKER; + entity.parentObject = stickerSet; + entity.text = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true).getAbsolutePath(); + entity.x = .5f - (float) Math.min(w, h) / w / 2f; + entity.y = .5f - (float) Math.min(w, h) / h / 2f; + entity.width = (float) Math.min(w, h) / w; + entity.height = (float) Math.min(w, h) / h; + float side = (float) Math.floor(size.width * 0.5); + entity.viewWidth = (int) side; + entity.viewHeight = (int) side; + entity.scale = 2f; + entity.document = document; + if (MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isVideoStickerDocument(document)) { + boolean isAnimatedSticker = MessageObject.isAnimatedStickerDocument(document, true); + entity.subType |= isAnimatedSticker ? 1 : 4; + } + entry.mediaEntities = new ArrayList<>(); + entry.mediaEntities.add(entity); + entry.averageDuration = 3000L; + if (MessageObject.isAnimatedStickerDocument(document, true)) { + File stickerFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); + if (stickerFile != null) { + try { + entry.averageDuration = (long) (RLottieDrawable.getDuration(stickerFile.getAbsolutePath(), null) * 1000L); + } catch (Exception e) { + FileLog.e(e); + } + } + } else if (MessageObject.isVideoStickerDocument(document)) { + entry.averageDuration = (long) (MessageObject.getDocumentDuration(document) * 1000L); + } + PhotoViewer.getInstance().setParentActivity(parentFragment.getParentActivity(), resourcesProvider); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public boolean allowCaption() { + return false; + } + }, chatActivity); + PhotoViewer.getInstance().enableStickerMode(document, true, null); + ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(stickerSet); + }, 300); + } } @Override @@ -481,7 +586,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not return clearsInputField; } - private void loadStickerSet() { + public void loadStickerSet() { if (inputStickerSet != null) { final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); if (stickerSet == null && inputStickerSet.short_name != null) { @@ -535,7 +640,12 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } optionsButton.setVisibility(View.VISIBLE); stickerSet = (TLRPC.TL_messages_stickerSet) response; - showEmoji = !stickerSet.set.masks; + mediaDataController.putStickerSet(stickerSet, false); + if (stickerSet != null && stickerSet.documents.isEmpty()) { + dismiss(); + return; + } + showEmoji = stickerSet != null && stickerSet.set != null && !stickerSet.set.masks; checkPremiumStickers(); mediaDataController.preloadStickerSetThumb(stickerSet); updateSendButton(); @@ -566,6 +676,18 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not checkPremiumStickers(); } + public void updateStickerSet(TLRPC.TL_messages_stickerSet set) { + stickerSet = set; + if (adapter != null) { + updateSendButton(); + updateFields(); + adapter.notifyDataSetChanged(); + } + updateDescription(); + MediaDataController.getInstance(currentAccount).preloadStickerSetThumb(stickerSet); + checkPremiumStickers(); + } + private void checkPremiumStickers() { if (stickerSet != null) { stickerSet = MessagesController.getInstance(currentAccount).filterPremiumStickers(stickerSet); @@ -728,7 +850,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not int w = AndroidUtilities.dp(36); rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4)); Theme.dialogs_onlineCirclePaint.setColor(getThemedColor(Theme.key_sheet_scrollUp)); - Theme.dialogs_onlineCirclePaint.setAlpha((int) (255 * Math.max(0, Math.min(1f, (y - AndroidUtilities.statusBarHeight) / (float) AndroidUtilities.dp(16))))); + Theme.dialogs_onlineCirclePaint.setAlpha((int) (Theme.dialogs_onlineCirclePaint.getAlpha() * Math.max(0, Math.min(1f, (y - AndroidUtilities.statusBarHeight) / (float) AndroidUtilities.dp(16))))); canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); updateLightStatusBar(statusBarHeight > AndroidUtilities.statusBarHeight / 2); @@ -813,6 +935,9 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not if (source.getItemViewType() != target.getItemViewType()) { return false; } + if (stickerSet == null) { + return false; + } int fromPosition = source.getAdapterPosition(); int toPosition = target.getAdapterPosition(); TLRPC.Document removed = stickerSet.documents.remove(fromPosition); @@ -822,6 +947,11 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not return true; } + @Override + public void onMoved(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) { + + } + @Override public int getDragDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { if (viewHolder.getItemViewType() == GridAdapter.TYPE_ADD_STICKER) { @@ -837,11 +967,6 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not TLRPC.TL_stickers_changeStickerPosition req = new TLRPC.TL_stickers_changeStickerPosition(); req.position = movedPos; req.sticker = MediaDataController.getInputStickerSetItem(draggedDocument, "").document; - AndroidUtilities.runOnUIThread(() -> ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 2, null, false, false); - } - })), 200); movedPos = -1; draggedDocument = null; } else if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { @@ -1146,6 +1271,9 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not deleteItem.getRightIcon().setColorFilter(redColor); } } + if (optionsButton.getPopupLayout() != null) { + optionsButton.getPopupLayout().requestLayout(); + } } private void updateSendButton() { @@ -1261,10 +1389,29 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not FileLog.e(e); } } else if (id == 3) { - enableEditMode(); + if (isEditModeEnabled) { + disableEditMode(); + } else { + enableEditMode(); + } } else if (id == 4) { - StickersDialogs.showNameEditorDialog(stickerSet.set, resourcesProvider, getContext(), arg -> { - titleTextView.setText(arg); + StickersDialogs.showNameEditorDialog(stickerSet.set, resourcesProvider, getContext(), (text, whenDone) -> { + titleTextView.setText(text); + TLRPC.TL_stickers_renameStickerSet req = new TLRPC.TL_stickers_renameStickerSet(); + req.stickerset = MediaDataController.getInputStickerSet(stickerSet.set); + req.title = text.toString(); + ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; + if (response instanceof TLRPC.TL_messages_stickerSet) { + TLRPC.TL_messages_stickerSet newset = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(UserConfig.selectedAccount).putStickerSet(newset); + if (!MediaDataController.getInstance(UserConfig.selectedAccount).isStickerPackInstalled(newset.set.id)) { + MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, newset, 2, null, false, false); + } + success = true; + } + whenDone.run(success); + })); }); } else if (id == 5) { StickersDialogs.showDeleteForEveryOneDialog(stickerSet.set, resourcesProvider, getContext(), () -> { @@ -1278,7 +1425,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not if (titleTextView == null) { return; } - if (stickerSet != null) { + if (stickerSet != null && stickerSet.documents != null && !stickerSet.documents.isEmpty()) { SpannableStringBuilder stringBuilder = null; CharSequence title = stickerSet.set.title; title = Emoji.replaceEmoji(title, titleTextView.getPaint().getFontMetricsInt(), dp(18), false); @@ -1712,22 +1859,25 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not setScrollOffsetY(gridView.getPaddingTop()); return; } - View child = gridView.getChildAt(0); - RecyclerListView.Holder holder = (RecyclerListView.Holder) gridView.findContainingViewHolder(child); - int top = child.getTop(); + int firstChildPosition = -1; + View firstChild = null; + for (int i = 0; i < gridView.getChildCount(); ++i) { + View child = gridView.getChildAt(i); + int position = gridView.getChildAdapterPosition(child); + if (firstChildPosition == -1 || firstChildPosition > position) { + firstChild = child; + firstChildPosition = position; + } + } int newOffset = 0; - if (top >= 0 && holder != null && holder.getAdapterPosition() == 0) { - newOffset = top; + if (firstChild != null && firstChild.getTop() >= 0) { + newOffset = (int) firstChild.getTop(); runShadowAnimation(0, false); } else { runShadowAnimation(0, true); } -// if (layoutManager.findLastCompletelyVisibleItemPosition() == adapter.getItemCount() - 1) { -// runShadowAnimation(1, false); -// } else { runShadowAnimation(1, true); -// } if (scrollOffsetY != newOffset) { setScrollOffsetY(newOffset); @@ -1736,7 +1886,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not private void setScrollOffsetY(int newOffset) { scrollOffsetY = newOffset; - gridView.setTopGlowOffset(newOffset); +// gridView.setTopGlowOffset(newOffset); if (stickerSetCovereds == null) { titleTextView.setTranslationY(newOffset); if (descriptionTextView != null) { @@ -1926,7 +2076,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not newStickerSet = mediaDataController.getStickerSetById(inputStickerSet.id); } } - if (newStickerSet != stickerSet) { + if (newStickerSet != null && newStickerSet != stickerSet) { stickerSet = newStickerSet; loadStickerSet(); } @@ -2159,6 +2309,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not if (stickerSet == null) return; cell.setSticker(stickerSet.documents.get(position), null, stickerSet, null, showEmoji, isEditModeEnabled); cell.editModeIcon.setOnClickListener(v -> { + ContentPreviewViewer.getInstance().setDelegate(previewDelegate); ContentPreviewViewer.getInstance().showMenuFor(cell); }); } @@ -2215,7 +2366,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not totalItems = importingStickersPaths.size(); } else { totalItems = stickerSet != null ? stickerSet.documents.size() : 0; - if (stickerSet != null && stickerSet.set.creator && !DISABLE_STICKER_EDITOR && !stickerSet.set.masks && !stickerSet.set.emojis) { + if (stickerSet != null && stickerSet.set.creator && stickerSet.documents.size() < STICKERS_MAX_COUNT && !DISABLE_STICKER_EDITOR && !stickerSet.set.masks && !stickerSet.set.emojis) { totalItems++; } } @@ -2262,7 +2413,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } }); optionsButton.postDelayed(() -> adapter.notifyDataSetChanged(), 200); - optionsButton.animate().alpha(0f).start(); +// optionsButton.animate().alpha(0f).start(); pickerBottomLayout.setText(LocaleController.getString(R.string.Done), true); } @@ -2280,7 +2431,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } }); optionsButton.postDelayed(() -> adapter.notifyDataSetChanged(), 200); - optionsButton.animate().alpha(1f).start(); +// optionsButton.animate().alpha(1f).start(); pickerBottomLayout.setText(LocaleController.getString(R.string.EditStickers), true); } @@ -2354,6 +2505,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } public void startShake() { + stopShake(false); init(); for (int i = 0; i < MAX_SHAKERS; i++) { final int pos = i; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java index e2c87b9c3..ae2637dd0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java @@ -17,6 +17,8 @@ import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BotWebViewVibrationEffect; +import org.telegram.messenger.FileRefController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; @@ -33,6 +35,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.ContentPreviewViewer; +import org.telegram.ui.Stories.DarkThemeResourceProvider; import org.telegram.ui.Stories.recorder.EmojiBottomSheet; import java.util.ArrayList; @@ -42,7 +45,7 @@ public class StickersDialogs { return Theme.getColor(key, resourcesProvider); } - public static void showNameEditorDialog(TLRPC.StickerSet set, Theme.ResourcesProvider resourcesProvider, Context context, Utilities.Callback callback) { + public static void showNameEditorDialog(TLRPC.StickerSet set, Theme.ResourcesProvider resourcesProvider, Context context, Utilities.Callback2> callback) { AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); boolean editMode = set != null; builder.setTitle(LocaleController.getString(editMode ? R.string.EditStickerPack : R.string.NewStickerPack)); @@ -101,6 +104,7 @@ public class StickersDialogs { @Override public void afterTextChanged(Editable s) { checkTextView.setNumber(maxLength - Character.codePointCount(s, 0, s.length()), true); + editText.setErrorText(null); } }); if (editMode) { @@ -111,20 +115,27 @@ public class StickersDialogs { builder.setCustomViewOffset(4); builder.setPositiveButton(LocaleController.getString(editMode ? R.string.Done : R.string.Create), (dialog, i) -> { CharSequence text = editText.getText().toString().trim(); - if (!TextUtils.isEmpty(text)) { + if (TextUtils.isEmpty(text) || TextUtils.isEmpty(AndroidUtilities.translitSafe(text.toString()))) { + editText.setErrorText("."); + AndroidUtilities.shakeViewSpring(editText, -6); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + AndroidUtilities.showKeyboard(editText); + } else { AndroidUtilities.hideKeyboard(editText); - dialog.dismiss(); - callback.run(text); - if (editMode) { - TLRPC.TL_stickers_renameStickerSet req = new TLRPC.TL_stickers_renameStickerSet(); - req.stickerset = MediaDataController.getInputStickerSet(set); - req.title = text.toString(); - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 2, null, false, false); - } - })); - } + if (callback == null) return; + AlertDialog progressDialog = new AlertDialog(context, AlertDialog.ALERT_TYPE_SPINNER, editMode ? null : new DarkThemeResourceProvider()); + progressDialog.showDelayed(250); + callback.run(text, success -> { + progressDialog.dismiss(); + if (success) { + dialog.dismiss(); + } else { + editText.setErrorText("."); + AndroidUtilities.shakeViewSpring(editText, -6); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + AndroidUtilities.showKeyboard(editText); + } + }); } }); builder.setNegativeButton(LocaleController.getString(R.string.Cancel), (dialog, which) -> { @@ -165,23 +176,52 @@ public class StickersDialogs { } private static void openStickerPickerDialog(TLRPC.TL_messages_stickerSet stickerSet, BaseFragment fragment, Theme.ResourcesProvider resourcesProvider) { - EmojiBottomSheet sheet = new EmojiBottomSheet(fragment.getContext(), true, resourcesProvider); + final int currentAccount = UserConfig.selectedAccount; + Context context = fragment.getContext(); + EmojiBottomSheet sheet = new EmojiBottomSheet(context, true, resourcesProvider, false); sheet.whenDocumentSelected((parentObject, document, a) -> { - String emoji = MessageObject.findAnimatedEmojiEmoticon(document, "\uD83D\uDE00", UserConfig.selectedAccount); +// if (stickerSet != null) { +// boolean found = false; +// for (int i = 0; i < stickerSet.documents.size(); ++i) { +// if (stickerSet.documents.get(i).id == document.id) { +// found = true; +// break; +// } +// } +// if (found) { +// BulletinFactory.of(sheet.getContainer(), resourcesProvider).createSimpleBulletin(R.raw.error, LocaleController.formatString(R.string.StickersStickerAlreadyThere, stickerSet.set.title)).show(true); +// return false; +// } +// } + String emoji = MessageObject.findAnimatedEmojiEmoticon(document, "\uD83D\uDE00", currentAccount); if (TextUtils.isEmpty(emoji)) { emoji = "\uD83D\uDE00"; } + AlertDialog progressDialog = new AlertDialog(context, AlertDialog.ALERT_TYPE_SPINNER); TLRPC.TL_stickers_addStickerToSet req = new TLRPC.TL_stickers_addStickerToSet(); req.stickerset = MediaDataController.getInputStickerSet(stickerSet.set); req.sticker = MediaDataController.getInputStickerSetItem(document, emoji); ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + progressDialog.dismiss(); if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 1, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, document), 250); + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); + if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(set.set.id)) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); + } + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, document, null, false), 250); } else if (error != null) { - BulletinFactory.showError(error); + if (FileRefController.isFileRefError(error.text)) { + FileRefController.getInstance(currentAccount).requestReference(parentObject, req); + } else { + BulletinFactory.showError(error); + } } })); + try { + progressDialog.showDelayed(350); + } catch (Exception e) {} + return true; }); if (fragment.visibleDialog != null) { sheet.show(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java index 98cf9c767..e6a1d8d1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java @@ -50,9 +50,12 @@ import java.util.Arrays; public class SuggestEmojiView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + public final static int DIRECTION_TO_BOTTOM = 0; + public final static int DIRECTION_TO_TOP = 1; + private final int currentAccount; private final Theme.ResourcesProvider resourcesProvider; - private final ChatActivityEnterView enterView; + private AnchorViewDelegate enterView; @Nullable private FrameLayout containerView; @@ -60,6 +63,18 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. private RecyclerListView listView; @Nullable private Adapter adapter; + private int direction = DIRECTION_TO_BOTTOM; + private int horizontalPadding = AndroidUtilities.dp(10); + + public interface AnchorViewDelegate { + BaseFragment getParentFragment(); + void setFieldText(CharSequence text); + void addTextChangedListener(TextWatcher watcher); + int getVisibility(); + EditTextBoldCursor getEditField(); + CharSequence getFieldText(); + Editable getEditText(); + } private ContentPreviewViewer.ContentPreviewViewerDelegate previewDelegate; private ContentPreviewViewer.ContentPreviewViewerDelegate getPreviewDelegate() { @@ -75,8 +90,12 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. if (enterView == null) { return false; } - ChatActivity fragment = enterView.getParentFragment(); - return fragment != null && fragment.canSendMessage() && (UserConfig.getInstance(UserConfig.selectedAccount).isPremium() || fragment.getCurrentUser() != null && UserObject.isUserSelf(fragment.getCurrentUser())); + BaseFragment fragment = enterView.getParentFragment(); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + return chatActivity.canSendMessage() && (UserConfig.getInstance(UserConfig.selectedAccount).isPremium() || chatActivity.getCurrentUser() != null && UserObject.isUserSelf(chatActivity.getCurrentUser())); + } + return false; } @Override @@ -84,13 +103,19 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. if (enterView == null) { return; } - ChatActivity fragment = enterView.getParentFragment(); - fragment.sendAnimatedEmoji(emoji, true, 0); - enterView.setFieldText(""); + BaseFragment fragment = enterView.getParentFragment(); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + chatActivity.sendAnimatedEmoji(emoji, true, 0); + enterView.setFieldText(""); + } } @Override public boolean needCopy(TLRPC.Document document) { + if (isCopyForbidden) { + return false; + } return UserConfig.getInstance(UserConfig.selectedAccount).isPremium(); } @@ -105,6 +130,9 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. @Override public Boolean canSetAsStatus(TLRPC.Document document) { + if (isSetAsStatusForbidden) { + return null; + } if (!UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) { return null; } @@ -160,8 +188,13 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. if (enterView == null) { return false; } - ChatActivity fragment = enterView.getParentFragment(); - return fragment.isInScheduleMode(); + BaseFragment fragment = enterView.getParentFragment(); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + return chatActivity.isInScheduleMode(); + } else { + return false; + } } @Override @@ -180,8 +213,10 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. @Nullable private ArrayList keywordResults; private boolean clear; + private boolean isCopyForbidden; + private boolean isSetAsStatusForbidden; - public SuggestEmojiView(Context context, int currentAccount, ChatActivityEnterView enterView, Theme.ResourcesProvider resourcesProvider) { + public SuggestEmojiView(Context context, int currentAccount, AnchorViewDelegate enterView, Theme.ResourcesProvider resourcesProvider) { super(context); this.currentAccount = currentAccount; this.enterView = enterView; @@ -190,6 +225,14 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. postDelayed(() -> MediaDataController.getInstance(currentAccount).checkStickers(MediaDataController.TYPE_EMOJIPACKS), 260); } + public void forbidCopy() { + isCopyForbidden = true; + } + + public void forbidSetAsStatus() { + isSetAsStatusForbidden = true; + } + private void createListView() { if (listView != null) { return; @@ -208,7 +251,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - this.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(8), AndroidUtilities.dp(10), AndroidUtilities.dp(6.66f)); + this.setPadding(horizontalPadding, direction == DIRECTION_TO_BOTTOM ? AndroidUtilities.dp(8) : AndroidUtilities.dp(6.66f), horizontalPadding, direction == DIRECTION_TO_BOTTOM ? AndroidUtilities.dp(6.66f) : AndroidUtilities.dp(8)); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -279,18 +322,36 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44 + 8)); addView(containerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 8 + 44 + 8 + 6.66f, Gravity.BOTTOM)); - enterView.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override - public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override - public void afterTextChanged(Editable editable) { - if (enterView.getVisibility() == View.VISIBLE) { - fireUpdate(); + if (enterView != null) { + enterView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } - } - }); + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + if (enterView != null && enterView.getVisibility() == View.VISIBLE) { + fireUpdate(); + } + } + }); + } + } + + public void setDelegate(AnchorViewDelegate delegate) { + this.enterView = delegate; + } + + public void setHorizontalPadding(int padding) { + this.horizontalPadding = padding; + } + + public AnchorViewDelegate getDelegate() { + return enterView; } public void onTextSelectionChanged(int start, int end) { @@ -301,6 +362,17 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. return show; } + public int getDirection() { + return direction; + } + + public void setDirection(int direction) { + if (this.direction != direction) { + this.direction = direction; + requestLayout(); + } + } + public void updateColors() { if (backgroundPaint != null) { backgroundPaint.setColor(Theme.getColor(Theme.key_chat_stickersHintPanel, resourcesProvider)); @@ -671,7 +743,11 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. float center = listViewCenterAnimated.set((listViewLeft + listViewRight) / 2f, force); if (enterView != null && enterView.getEditField() != null) { - containerView.setTranslationY(-enterView.getEditField().getHeight() - enterView.getEditField().getScrollY() + lastSpanY + AndroidUtilities.dp(5)); + if (direction == DIRECTION_TO_BOTTOM) { + containerView.setTranslationY(-enterView.getEditField().getHeight() - enterView.getEditField().getScrollY() + lastSpanY + AndroidUtilities.dp(5)); + } else if (direction == DIRECTION_TO_TOP) { + containerView.setTranslationY(-getMeasuredHeight() - enterView.getEditField().getScrollY() + lastSpanY + AndroidUtilities.dp(20) + containerView.getHeight()); + } } int listViewPaddingLeft = (int) Math.max(this.arrowX - Math.max(width / 4f, Math.min(width / 2f, AndroidUtilities.dp(66))) - listView.getLeft(), 0); if (listView.getPaddingLeft() != listViewPaddingLeft) { @@ -683,28 +759,45 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. listView.setTranslationX(listViewPaddingLeftI - listViewPaddingLeft); float left = center - width / 2f + listView.getPaddingLeft() + listView.getTranslationX(); - float top = listView.getTop() + listView.getTranslationY() + listView.getPaddingTop(); + float top = listView.getTop() + listView.getTranslationY() + listView.getPaddingTop() + (direction == DIRECTION_TO_BOTTOM ? 0: AndroidUtilities.dp(6.66f)); float right = Math.min(center + width / 2f + listView.getPaddingLeft() + listView.getTranslationX(), getWidth() - containerView.getPaddingRight()); - float bottom = listView.getBottom() + listView.getTranslationY() - AndroidUtilities.dp(6.66f); + float bottom = listView.getBottom() + listView.getTranslationY() - (direction == DIRECTION_TO_BOTTOM ? AndroidUtilities.dp(6.66f) : 0); float R = Math.min(AndroidUtilities.dp(9), width / 2f), D = R * 2; - AndroidUtilities.rectTmp.set(left, bottom - D, left + D, bottom); - path.arcTo(AndroidUtilities.rectTmp, 90, 90); + if (direction == DIRECTION_TO_BOTTOM) { + AndroidUtilities.rectTmp.set(left, bottom - D, left + D, bottom); + path.arcTo(AndroidUtilities.rectTmp, 90, 90); - AndroidUtilities.rectTmp.set(left, top, left + D, top + D); - path.arcTo(AndroidUtilities.rectTmp, -180, 90); + AndroidUtilities.rectTmp.set(left, top, left + D, top + D); + path.arcTo(AndroidUtilities.rectTmp, -180, 90); - AndroidUtilities.rectTmp.set(right - D, top, right, top + D); - path.arcTo(AndroidUtilities.rectTmp, -90, 90); + AndroidUtilities.rectTmp.set(right - D, top, right, top + D); + path.arcTo(AndroidUtilities.rectTmp, -90, 90); - AndroidUtilities.rectTmp.set(right - D, bottom - D, right, bottom); - path.arcTo(AndroidUtilities.rectTmp, 0, 90); + AndroidUtilities.rectTmp.set(right - D, bottom - D, right, bottom); + path.arcTo(AndroidUtilities.rectTmp, 0, 90); - path.lineTo(arrowX + AndroidUtilities.dp(8.66f), bottom); - path.lineTo(arrowX, bottom + AndroidUtilities.dp(6.66f)); - path.lineTo(arrowX - AndroidUtilities.dp(8.66f), bottom); + path.lineTo(arrowX + AndroidUtilities.dp(8.66f), bottom); + path.lineTo(arrowX, bottom + AndroidUtilities.dp(6.66f)); + path.lineTo(arrowX - AndroidUtilities.dp(8.66f), bottom); + } else if (direction == DIRECTION_TO_TOP) { + AndroidUtilities.rectTmp.set(right - D, top, right, top + D); + path.arcTo(AndroidUtilities.rectTmp, -90, 90); + AndroidUtilities.rectTmp.set(right - D, bottom - D, right, bottom); + path.arcTo(AndroidUtilities.rectTmp, 0, 90); + + AndroidUtilities.rectTmp.set(left, bottom - D, left + D, bottom); + path.arcTo(AndroidUtilities.rectTmp, 90, 90); + + AndroidUtilities.rectTmp.set(left, top, left + D, top + D); + path.arcTo(AndroidUtilities.rectTmp, -180, 90); + + path.lineTo(arrowX - AndroidUtilities.dp(8.66f), top); + path.lineTo(arrowX, top - AndroidUtilities.dp(6.66f)); + path.lineTo(arrowX + AndroidUtilities.dp(8.66f), top); + } path.close(); if (backgroundPaint == null) { @@ -716,7 +809,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. if (showT1 < 1) { circlePath.rewind(); - float cx = arrowX, cy = bottom + AndroidUtilities.dp(6.66f); + float cx = arrowX, cy = (direction == DIRECTION_TO_BOTTOM) ? bottom + AndroidUtilities.dp(6.66f) : top - AndroidUtilities.dp(6.66f); float toRadius = (float) Math.sqrt(Math.max( Math.max( Math.pow(cx - left, 2) + Math.pow(cy - top, 2), @@ -828,17 +921,22 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. } } + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD; + } + public void invalidateContent() { if (containerView != null) { containerView.invalidate(); } } - public static class EmojiImageView extends View { + public class EmojiImageView extends View { private String emoji; public Drawable drawable; private boolean attached; + private int direction = DIRECTION_TO_BOTTOM; private AnimatedFloat pressed = new AnimatedFloat(this, 350, new OvershootInterpolator(5.0f)); @@ -849,20 +947,20 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. private final int paddingDp = 3; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setPadding(AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp + 6.66f)); + setPadding(AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp + (direction == DIRECTION_TO_BOTTOM ? 0 : 6.66f)), AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp + (direction == DIRECTION_TO_BOTTOM ? 6.66f : 0))); super.onMeasure( MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(44), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(44 + 8), MeasureSpec.EXACTLY) ); } - private void setEmoji(String emoji) { + private void setEmoji(String emoji, int direction) { this.emoji = emoji; if (emoji != null && emoji.startsWith("animated_")) { try { long documentId = Long.parseLong(emoji.substring(9)); if (!(drawable instanceof AnimatedEmojiDrawable) || ((AnimatedEmojiDrawable) drawable).getDocumentId() != documentId) { - setImageDrawable(AnimatedEmojiDrawable.make(UserConfig.selectedAccount, AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, documentId)); + setImageDrawable(AnimatedEmojiDrawable.make(UserConfig.selectedAccount, emojiCacheType(), documentId)); } } catch (Exception ignore) { setImageDrawable(null); @@ -870,6 +968,10 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. } else { setImageDrawable(Emoji.getEmojiBigDrawable(emoji)); } + if (this.direction != direction) { + this.direction = direction; + requestLayout(); + } } public void setImageDrawable(@Nullable Drawable drawable) { @@ -882,6 +984,11 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. } } + public void setDirection(int direction) { + this.direction = direction; + invalidate(); + } + @Override public void setPressed(boolean pressed) { super.setPressed(pressed); @@ -929,7 +1036,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. } } - private static class Adapter extends RecyclerListView.SelectionAdapter { + private class Adapter extends RecyclerListView.SelectionAdapter { SuggestEmojiView suggestEmojiView; public Adapter(SuggestEmojiView suggestEmojiView) { @@ -954,7 +1061,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - ((EmojiImageView) holder.itemView).setEmoji(suggestEmojiView.keywordResults == null ? null : suggestEmojiView.keywordResults.get(position).emoji); + ((EmojiImageView) holder.itemView).setEmoji(suggestEmojiView.keywordResults == null ? null : suggestEmojiView.keywordResults.get(position).emoji, suggestEmojiView.getDirection()); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index 4fb546f17..8eec08eb4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -471,7 +471,7 @@ public class Switch extends View { colorProgress = progress; } - color1 = processColor(Theme.getColor(thumbColorKey, resourcesProvider)); + color1 = Theme.getColor(thumbColorKey, resourcesProvider); color2 = processColor(Theme.getColor(thumbCheckedColorKey, resourcesProvider)); r1 = Color.red(color1); r2 = Color.red(color2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java index 40f9827ec..c1080e586 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java @@ -28,6 +28,7 @@ import com.google.zxing.common.detector.MathUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DispatchQueue; +import org.telegram.messenger.EmuDetector; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessageObject; @@ -124,6 +125,7 @@ public class ThanosEffect extends TextureView { drawThread = null; } drawThread = new DrawingThread(surface, ThanosEffect.this::invalidate, ThanosEffect.this::destroy, width, height); + drawThread.isEmulator = EmuDetector.with(getContext()).detect(); if (!toSet.isEmpty()) { for (int i = 0; i < toSet.size(); ++i) { ToSet toSetObj = toSet.get(i); @@ -258,6 +260,7 @@ public class ThanosEffect extends TextureView { private static class DrawingThread extends DispatchQueue { + private boolean isEmulator; private volatile boolean alive = true; private final SurfaceTexture surfaceTexture; private final Runnable invalidate; @@ -435,6 +438,8 @@ public class ThanosEffect extends TextureView { private int densityHandle; private int longevityHandle; private int offsetHandle; + private int scaleHandle; + private int uvOffsetHandle; public volatile boolean running; private final ArrayList pendingAnimations = new ArrayList<>(); @@ -547,6 +552,8 @@ public class ThanosEffect extends TextureView { densityHandle = GLES31.glGetUniformLocation(drawProgram, "dp"); longevityHandle = GLES31.glGetUniformLocation(drawProgram, "longevity"); offsetHandle = GLES31.glGetUniformLocation(drawProgram, "offset"); + scaleHandle = GLES31.glGetUniformLocation(drawProgram, "scale"); + uvOffsetHandle = GLES31.glGetUniformLocation(drawProgram, "uvOffset"); GLES31.glViewport(0, 0, width, height); GLES31.glEnable(GLES31.GL_BLEND); @@ -737,6 +744,12 @@ public class ThanosEffect extends TextureView { animation.bitmap.recycle(); animation.bitmap = null; + if (animation.isPhotoEditor) { + for (Animation anim : pendingAnimations) { + anim.done(true); + } + pendingAnimations.clear(); + } pendingAnimations.add(animation); running = true; @@ -776,8 +789,10 @@ public class ThanosEffect extends TextureView { public final int[] buffer = new int[2]; private Bitmap bitmap; + private boolean isPhotoEditor; public Animation(Matrix matrix, Bitmap bitmap, Runnable whenStarted, Runnable whenDone) { + isPhotoEditor = true; float[] v = new float[] { 0, 0, 0, 1, 1, 0, 1, 1 }; matrix.mapPoints(v); left = v[0]; @@ -789,6 +804,8 @@ public class ThanosEffect extends TextureView { retrieveMatrixValues(); startCallback = whenStarted; doneCallback = whenDone; + longevity = 4f; + time = -.1f; // longevity = 1.5f * Utilities.clamp(viewWidth / (float) AndroidUtilities.displaySize.x, .6f, 0.2f); this.bitmap = bitmap; } @@ -1046,7 +1063,7 @@ public class ThanosEffect extends TextureView { } public void calcParticlesGrid(float part) { - final int maxParticlesCount; + int maxParticlesCount; switch (SharedConfig.getDevicePerformanceClass()) { case SharedConfig.PERFORMANCE_CLASS_HIGH: maxParticlesCount = 120_000; @@ -1059,6 +1076,12 @@ public class ThanosEffect extends TextureView { maxParticlesCount = 30_000; break; } + if (isEmulator) { + maxParticlesCount = 120_000; + } + if (isPhotoEditor) { + maxParticlesCount /= 2; + } float p = Math.max(AndroidUtilities.dpf2(.4f), 1); particlesCount = Utilities.clamp((int) (viewWidth * viewHeight / (p * p)), (int) (maxParticlesCount * part), 10); @@ -1174,6 +1197,8 @@ public class ThanosEffect extends TextureView { GLES31.glUniform1f(particlesCountHandle, particlesCount); GLES31.glUniform3f(gridSizeHandle, gridWidth, gridHeight, gridSize); GLES31.glUniform2f(offsetHandle, offsetLeft, offsetTop); + GLES31.glUniform1f(scaleHandle, isPhotoEditor ? .8f : 1); + GLES31.glUniform1f(uvOffsetHandle, isPhotoEditor ? 1f : .6f); GLES31.glUniform2f(rectSizeHandle, viewWidth, viewHeight); GLES31.glUniform1f(seedHandle, seed); @@ -1216,7 +1241,7 @@ public class ThanosEffect extends TextureView { } public boolean isDead() { - return time > longevity + .9f; + return time > longevity + (isPhotoEditor ? 2f : .9f); } public void done(boolean runCallback) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java index 980b286fe..e50dc3cb7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java @@ -4,7 +4,9 @@ package org.telegram.ui.Components; import android.text.TextUtils; import android.view.View; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stats; import org.telegram.ui.Business.BusinessLinksActivity; @@ -21,13 +23,15 @@ public class UItem extends AdapterWithDiffUtils.Item { public View view; public int id; public boolean checked; + public boolean collapsed; public boolean enabled = true; + public int pad; public boolean hideDivider; public int iconResId; - public int backgroundKey; public CharSequence text, subtext, textValue; + public CharSequence animatedText; public String[] texts; - public boolean accent, red, transparent; + public boolean accent, red, transparent, locked; public boolean include; public long dialogId; @@ -37,10 +41,12 @@ public class UItem extends AdapterWithDiffUtils.Item { public int intValue; public Utilities.Callback intCallback; - public Runnable clickCallback; + public View.OnClickListener clickCallback; public Object object; + public boolean withUsername = true; + public UItem(int viewType, boolean selectable) { super(viewType, selectable); @@ -58,6 +64,13 @@ public class UItem extends AdapterWithDiffUtils.Item { return i; } + public static UItem asAnimatedHeader(int id, CharSequence text) { + UItem i = new UItem(UniversalAdapter.VIEW_TYPE_ANIMATED_HEADER, false); + i.id = id; + i.animatedText = text; + return i; + } + public static UItem asLargeHeader(CharSequence text) { UItem i = new UItem(UniversalAdapter.VIEW_TYPE_LARGE_HEADER, false); i.text = text; @@ -117,13 +130,20 @@ public class UItem extends AdapterWithDiffUtils.Item { return i; } - public static UItem asButton(int id, CharSequence text, TLRPC.Document sticker) { + public static UItem asStickerButton(int id, CharSequence text, TLRPC.Document sticker) { UItem i = new UItem(UniversalAdapter.VIEW_TYPE_TEXT, false); i.id = id; i.text = text; i.object = sticker; return i; } + public static UItem asStickerButton(int id, CharSequence text, String stickerPath) { + UItem i = new UItem(UniversalAdapter.VIEW_TYPE_TEXT, false); + i.id = id; + i.text = text; + i.object = stickerPath; + return i; + } public static UItem asRippleCheck(int id, CharSequence text) { UItem i = new UItem(UniversalAdapter.VIEW_TYPE_CHECKRIPPLE, false); @@ -281,11 +301,106 @@ public class UItem extends AdapterWithDiffUtils.Item { return item; } - public UItem setCloseIcon(Runnable onCloseClick) { + public static UItem asRoundCheckbox(int id, CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX, false); + item.id = id; + item.text = text; + return item; + } + + public static UItem asRoundGroupCheckbox(int id, CharSequence text, CharSequence subtext) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_ROUND_GROUP_CHECKBOX, false); + item.id = id; + item.text = text; + item.animatedText = subtext; + return item; + } + + public static UItem asUserGroupCheckbox(int id, CharSequence text, CharSequence subtext) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_USER_GROUP_CHECKBOX, false); + item.id = id; + item.text = text; + item.animatedText = subtext; + return item; + } + + public static UItem asUserCheckbox(int id, TLObject user) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_USER_CHECKBOX, false); + item.id = id; + item.object = user; + return item; + } + + public static UItem asShadowCollapseButton(int id, CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_SHADOW_COLLAPSE_BUTTON, false); + item.id = id; + item.animatedText = text; + return item; + } + + public static UItem asSwitch(int id, CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_SWITCH, false); + item.id = id; + item.text = text; + return item; + } + + public static UItem asExpandableSwitch(int id, CharSequence text, CharSequence subText) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_EXPANDABLE_SWITCH, false); + item.id = id; + item.text = text; + item.animatedText = subText; + return item; + } + + public static UItem asGraySection(CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_GRAY_SECTION, false); + item.text = text; + return item; + } + + public static UItem asGraySection(CharSequence text, CharSequence button, View.OnClickListener onClickListener) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_GRAY_SECTION, false); + item.text = text; + item.subtext = button; + item.clickCallback = onClickListener; + return item; + } + + public static UItem asProfileCell(TLObject obj) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_PROFILE_CELL, false); + item.object = obj; + return item; + } + + public static UItem asSearchMessage(MessageObject messageObject) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_SEARCH_MESSAGE, false); + item.object = messageObject; + return item; + } + + public static UItem asFlicker(int type) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_FLICKER, false); + item.intValue = type; + return item; + } + + + public UItem withUsername(boolean value) { + withUsername = value; + return this; + } + + public UItem setCloseIcon(View.OnClickListener onCloseClick) { clickCallback = onCloseClick; return this; } + public UItem setClickCallback(View.OnClickListener clickCallback) { + this.clickCallback = clickCallback; + return this; + } + public UItem setChecked(boolean checked) { this.checked = checked; if (viewType == UniversalAdapter.VIEW_TYPE_FILTER_CHAT) { @@ -294,11 +409,36 @@ public class UItem extends AdapterWithDiffUtils.Item { return this; } + public UItem setCollapsed(boolean collapsed) { + this.collapsed = collapsed; + return this; + } + + public UItem setPad(int pad) { + this.pad = pad; + return this; + } + + public UItem pad() { + this.pad = 1; + return this; + } + public UItem setEnabled(boolean enabled) { this.enabled = enabled; return this; } + public UItem setLocked(boolean locked) { + this.locked = locked; + return this; + } + + public UItem locked() { + this.locked = true; + return this; + } + public UItem red() { this.red = true; return this; @@ -314,15 +454,24 @@ public class UItem extends AdapterWithDiffUtils.Item { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UItem item = (UItem) o; + if (viewType != item.viewType) + return false; + if (viewType == UniversalAdapter.VIEW_TYPE_USER_GROUP_CHECKBOX || + viewType == UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX) { + return id == item.id; + } + if (viewType == UniversalAdapter.VIEW_TYPE_GRAY_SECTION) { + return TextUtils.equals(text, item.text); + } return ( - viewType == item.viewType && id == item.id && + pad == item.pad && dialogId == item.dialogId && iconResId == item.iconResId && - backgroundKey == item.backgroundKey && hideDivider == item.hideDivider && transparent == item.transparent && red == item.red && + locked == item.locked && accent == item.accent && TextUtils.equals(text, item.text) && TextUtils.equals(subtext, item.subtext) && @@ -332,4 +481,21 @@ public class UItem extends AdapterWithDiffUtils.Item { Objects.equals(object, item.object) ); } + + @Override + protected boolean contentsEquals(AdapterWithDiffUtils.Item o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UItem item = (UItem) o; + if (viewType != item.viewType) + return false; + if (viewType == UniversalAdapter.VIEW_TYPE_GRAY_SECTION) { + return TextUtils.equals(text, item.text) && TextUtils.equals(subtext, item.subtext); + } + if (viewType == UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX || + viewType == UniversalAdapter.VIEW_TYPE_USER_CHECKBOX) { + return id == item.id && TextUtils.equals(text, item.text) && checked == item.checked; + } + return super.contentsEquals(o); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java index 935ef7477..14c75b622 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java @@ -4,7 +4,12 @@ import static org.telegram.messenger.AndroidUtilities.dp; import android.content.Context; import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.text.SpannableStringBuilder; import android.text.TextUtils; +import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -14,20 +19,32 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; 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.messenger.UserObject; import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stats; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Business.BusinessLinksActivity; import org.telegram.ui.Business.QuickRepliesActivity; import org.telegram.ui.Business.QuickRepliesController; +import org.telegram.ui.Cells.CheckBoxCell; +import org.telegram.ui.Cells.CollapseTextCell; +import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.DialogRadioCell; +import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.NotificationsCheckCell; +import org.telegram.ui.Cells.ProfileChannelCell; +import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.SlideIntChooseView; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; +import org.telegram.ui.Cells.TextCheckCell2; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextRightIconCell; import org.telegram.ui.Cells.UserCell; @@ -82,11 +99,25 @@ public class UniversalAdapter extends AdapterWithDiffUtils { public static final int VIEW_TYPE_RIGHT_ICON_TEXT = 30; - private final RecyclerListView listView; + public static final int VIEW_TYPE_GRAY_SECTION = 31; + public static final int VIEW_TYPE_PROFILE_CELL = 32; + public static final int VIEW_TYPE_SEARCH_MESSAGE = 33; + public static final int VIEW_TYPE_FLICKER = 34; + public static final int VIEW_TYPE_ROUND_CHECKBOX = 35; + public static final int VIEW_TYPE_USER_GROUP_CHECKBOX = 36; + public static final int VIEW_TYPE_USER_CHECKBOX = 37; + public static final int VIEW_TYPE_SHADOW_COLLAPSE_BUTTON = 38; + public static final int VIEW_TYPE_SWITCH = 39; + public static final int VIEW_TYPE_EXPANDABLE_SWITCH = 40; + public static final int VIEW_TYPE_ROUND_GROUP_CHECKBOX = 41; + public static final int VIEW_TYPE_ANIMATED_HEADER = 42; + + protected final RecyclerListView listView; private final Context context; private final int currentAccount; private final int classGuid; - private final Utilities.Callback2, UniversalAdapter> fillItems; + private final boolean dialog; + protected Utilities.Callback2, UniversalAdapter> fillItems; private final Theme.ResourcesProvider resourcesProvider; private final ArrayList oldItems = new ArrayList<>(); @@ -101,12 +132,25 @@ public class UniversalAdapter extends AdapterWithDiffUtils { int classGuid, Utilities.Callback2, UniversalAdapter> fillItems, Theme.ResourcesProvider resourcesProvider + ) { + this(listView, context, currentAccount, classGuid, false, fillItems, resourcesProvider); + } + + public UniversalAdapter( + RecyclerListView listView, + Context context, + int currentAccount, + int classGuid, + boolean dialog, + Utilities.Callback2, UniversalAdapter> fillItems, + Theme.ResourcesProvider resourcesProvider ) { super(); this.listView = listView; this.context = context; this.currentAccount = currentAccount; this.classGuid = classGuid; + this.dialog = dialog; this.fillItems = fillItems; this.resourcesProvider = resourcesProvider; update(false); @@ -214,7 +258,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils { for (int i = 0; i < whiteSections.size(); ++i) { Section section = whiteSections.get(i); if (section.end < 0) continue; - listView.drawSectionBackground(canvas, section.start, section.end, getThemedColor(Theme.key_windowBackgroundWhite)); + listView.drawSectionBackground(canvas, section.start, section.end, getThemedColor(dialog ? Theme.key_dialogBackground : Theme.key_windowBackgroundWhite)); } } @@ -224,11 +268,13 @@ public class UniversalAdapter extends AdapterWithDiffUtils { items.clear(); whiteSections.clear(); reorderSections.clear(); - fillItems.run(items, this); - if (animated) { - setItems(oldItems, items); - } else { - notifyDataSetChanged(); + if (fillItems != null) { + fillItems.run(items, this); + if (animated) { + setItems(oldItems, items); + } else { + notifyDataSetChanged(); + } } } @@ -236,19 +282,27 @@ public class UniversalAdapter extends AdapterWithDiffUtils { @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; + final int key_background = dialog ? Theme.key_dialogBackground : Theme.key_windowBackgroundWhite; switch (viewType) { case VIEW_TYPE_HEADER: - view = new HeaderCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + if (dialog) { + view = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, 0, false, resourcesProvider); + } else { + view = new HeaderCell(context, resourcesProvider); + } + view.setBackgroundColor(getThemedColor(key_background)); + break; + case VIEW_TYPE_ANIMATED_HEADER: + view = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, 0, false, true, resourcesProvider); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_BLACK_HEADER: view = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlackText, 17, 15, false, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_LARGE_HEADER: - HeaderCell headerCell = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlackText, 23, 8, 10, false, resourcesProvider); + HeaderCell headerCell = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlackText, 23, 20, 0, false, resourcesProvider); headerCell.setTextSize(20); - headerCell.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); view = headerCell; break; case VIEW_TYPE_TOPVIEW: @@ -256,7 +310,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils { break; case VIEW_TYPE_TEXT: view = new TextCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_CHECK: case VIEW_TYPE_CHECKRIPPLE: @@ -267,17 +321,17 @@ public class UniversalAdapter extends AdapterWithDiffUtils { cell.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); cell.setHeight(56); } - cell.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + cell.setBackgroundColor(getThemedColor(key_background)); view = cell; break; case VIEW_TYPE_RADIO: view = new DialogRadioCell(context); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_TEXT_CHECK: case VIEW_TYPE_ICON_TEXT_CHECK: view = new NotificationsCheckCell(context, 21, 60, viewType == VIEW_TYPE_ICON_TEXT_CHECK, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_CUSTOM: view = new FrameLayout(context) { @@ -291,35 +345,35 @@ public class UniversalAdapter extends AdapterWithDiffUtils { case VIEW_TYPE_FILTER_CHAT_CHECK: UserCell userCell = new UserCell(context, 6, viewType == VIEW_TYPE_FILTER_CHAT_CHECK ? 3 : 0, false); userCell.setSelfAsSavedMessages(true); - userCell.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + userCell.setBackgroundColor(getThemedColor(key_background)); view = userCell; break; case VIEW_TYPE_USER_ADD: UserCell userCell2 = new UserCell(context, 6, 0, false, true); - userCell2.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + userCell2.setBackgroundColor(getThemedColor(key_background)); view = userCell2; break; case VIEW_TYPE_RADIO_USER: StoryPrivacyBottomSheet.UserCell userCell3 = new StoryPrivacyBottomSheet.UserCell(context, resourcesProvider); userCell3.setIsSendAs(false, false); - userCell3.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + userCell3.setBackgroundColor(getThemedColor(key_background)); view = userCell3; break; case VIEW_TYPE_SLIDE: view = new SlideChooseView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_INTSLIDE: view = new SlideIntChooseView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_QUICK_REPLY: view = new QuickRepliesActivity.QuickReplyView(context, onReordered != null, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_LARGE_QUICK_REPLY: view = new QuickRepliesActivity.LargeQuickReplyView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_CHART_LINEAR: case VIEW_TYPE_CHART_DOUBLE_LINEAR: @@ -331,26 +385,43 @@ public class UniversalAdapter extends AdapterWithDiffUtils { chartSharedUI = new BaseChartView.SharedUiComponents(); } view = new StatisticActivity.UniversalChartCell(context, currentAccount, viewType - VIEW_TYPE_CHART_LINEAR, chartSharedUI, classGuid); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_TRANSACTION: view = new ChannelMonetizationLayout.TransactionCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_PROCEED_OVERVIEW: view = new ChannelMonetizationLayout.ProceedOverviewCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_SPACE: view = new View(context); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_BUSINESS_LINK: view = new BusinessLinksActivity.BusinessLinkView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_RIGHT_ICON_TEXT: view = new TextRightIconCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(key_background)); + break; + case VIEW_TYPE_GRAY_SECTION: + view = new GraySectionCell(context, resourcesProvider); + break; + case VIEW_TYPE_PROFILE_CELL: + view = new ProfileSearchCell(context); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + break; + case VIEW_TYPE_SEARCH_MESSAGE: + view = new DialogCell(null, context, false, true); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + break; + case VIEW_TYPE_FLICKER: + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context, resourcesProvider); + flickerLoadingView.setIsSingleCell(true); + view = flickerLoadingView; view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); break; default: @@ -358,6 +429,33 @@ public class UniversalAdapter extends AdapterWithDiffUtils { case VIEW_TYPE_LARGE_SHADOW: view = new TextInfoPrivacyCell(context, resourcesProvider); break; + case VIEW_TYPE_ROUND_CHECKBOX: + case VIEW_TYPE_ROUND_GROUP_CHECKBOX: + case VIEW_TYPE_USER_GROUP_CHECKBOX: + case VIEW_TYPE_USER_CHECKBOX: + int checkBoxType = 0; + if (viewType == VIEW_TYPE_ROUND_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_ROUND; + } else if (viewType == VIEW_TYPE_USER_GROUP_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_USER_GROUP; + } else if (viewType == VIEW_TYPE_USER_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_USER; + } else if (viewType == VIEW_TYPE_ROUND_GROUP_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_ROUND_GROUP; + } + CheckBoxCell checkBoxCell = new CheckBoxCell(context, checkBoxType, 21, true, resourcesProvider); + checkBoxCell.getCheckBoxRound().setColor(Theme.key_switch2TrackChecked, Theme.key_radioBackground, Theme.key_checkboxCheck); + checkBoxCell.setBackgroundColor(getThemedColor(key_background)); + view = checkBoxCell; + break; + case VIEW_TYPE_SHADOW_COLLAPSE_BUTTON: + view = new CollapseTextCell(context, resourcesProvider); + break; + case VIEW_TYPE_SWITCH: + case VIEW_TYPE_EXPANDABLE_SWITCH: + view = new TextCheckCell2(context); + view.setBackgroundColor(getThemedColor(key_background)); + break; } return new RecyclerListView.Holder(view); } @@ -376,7 +474,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils { } private boolean isShadow(int viewType) { - return viewType == VIEW_TYPE_SHADOW || viewType == VIEW_TYPE_LARGE_SHADOW; + return viewType == VIEW_TYPE_SHADOW || viewType == VIEW_TYPE_LARGE_SHADOW || viewType == VIEW_TYPE_SHADOW_COLLAPSE_BUTTON || viewType == VIEW_TYPE_GRAY_SECTION || viewType == VIEW_TYPE_FLICKER; } @Override @@ -392,9 +490,11 @@ public class UniversalAdapter extends AdapterWithDiffUtils { case VIEW_TYPE_BLACK_HEADER: case VIEW_TYPE_LARGE_HEADER: ((HeaderCell) holder.itemView).setText(item.text); - if (item.backgroundKey != 0) { - holder.itemView.setBackgroundColor(getThemedColor(item.backgroundKey)); - } + break; + case VIEW_TYPE_ANIMATED_HEADER: + HeaderCell animatedHeaderCell = (HeaderCell) holder.itemView; + animatedHeaderCell.setText(item.animatedText, animatedHeaderCell.id == item.id); + animatedHeaderCell.id = item.id; break; case VIEW_TYPE_TOPVIEW: TopViewCell topCell = (TopViewCell) holder.itemView; @@ -409,6 +509,8 @@ public class UniversalAdapter extends AdapterWithDiffUtils { TextCell cell = (TextCell) holder.itemView; if (item.object instanceof TLRPC.Document) { cell.setTextAndSticker(item.text, (TLRPC.Document) item.object, divider); + } else if (item.object instanceof String) { + cell.setTextAndSticker(item.text, (String) item.object, divider); } else if (TextUtils.isEmpty(item.textValue)) { if (item.iconResId == 0) { cell.setText(item.text, divider); @@ -429,9 +531,6 @@ public class UniversalAdapter extends AdapterWithDiffUtils { } else { cell.setColors(Theme.key_windowBackgroundWhiteGrayIcon, Theme.key_windowBackgroundWhiteBlackText); } - if (item.backgroundKey != 0) { - cell.setBackgroundColor(getThemedColor(item.backgroundKey)); - } break; case VIEW_TYPE_CHECK: case VIEW_TYPE_CHECKRIPPLE: @@ -462,32 +561,48 @@ public class UniversalAdapter extends AdapterWithDiffUtils { break; case VIEW_TYPE_TEXT_CHECK: NotificationsCheckCell checkCell1 = (NotificationsCheckCell) holder.itemView; - checkCell1.setTextAndValueAndCheck(item.text, item.subtext, item.checked, divider); - checkCell1.setMultiline(item.subtext != null && item.subtext.toString().contains("\n")); + final boolean multiline = item.subtext != null && item.subtext.toString().contains("\n"); + checkCell1.setTextAndValueAndCheck(item.text, item.subtext, item.checked, 0, multiline, divider); break; case VIEW_TYPE_ICON_TEXT_CHECK: // TODO: image ((NotificationsCheckCell) holder.itemView).setTextAndValueAndCheck(item.text, item.subtext, item.checked, divider); break; + case VIEW_TYPE_SHADOW_COLLAPSE_BUTTON: case VIEW_TYPE_SHADOW: case VIEW_TYPE_LARGE_SHADOW: - TextInfoPrivacyCell cell2 = (TextInfoPrivacyCell) holder.itemView; - if (TextUtils.isEmpty(item.text)) { - cell2.setFixedSize(viewType == VIEW_TYPE_LARGE_SHADOW ? 220 : 12); - cell2.setText(""); - } else { - cell2.setFixedSize(0); - cell2.setText(item.text); - } - if (item.accent) { // asCenterShadow - cell2.setTextGravity(Gravity.CENTER); - cell2.getTextView().setWidth(Math.min(HintView2.cutInFancyHalf(cell2.getText(), cell2.getTextView().getPaint()), AndroidUtilities.displaySize.x - dp(60))); - cell2.getTextView().setPadding(0, dp(17), 0, dp(17)); - } else { - cell2.setTextGravity(Gravity.START); - cell2.getTextView().setMinWidth(0); - cell2.getTextView().setMaxWidth(AndroidUtilities.displaySize.x); - cell2.getTextView().setPadding(0, dp(10), 0, dp(17)); + View cell3 = null; + if (viewType == VIEW_TYPE_SHADOW || viewType == VIEW_TYPE_LARGE_SHADOW) { + TextInfoPrivacyCell cell2 = (TextInfoPrivacyCell) holder.itemView; + if (TextUtils.isEmpty(item.text)) { + cell2.setFixedSize(viewType == VIEW_TYPE_LARGE_SHADOW ? 220 : 12); + cell2.setText(""); + } else { + cell2.setFixedSize(0); + cell2.setText(item.text); + } + if (item.accent) { // asCenterShadow + cell2.setTextGravity(Gravity.CENTER); + cell2.getTextView().setWidth(Math.min(HintView2.cutInFancyHalf(cell2.getText(), cell2.getTextView().getPaint()), AndroidUtilities.displaySize.x - dp(60))); + cell2.getTextView().setPadding(0, dp(17), 0, dp(17)); + } else { + cell2.setTextGravity(Gravity.START); + cell2.getTextView().setMinWidth(0); + cell2.getTextView().setMaxWidth(AndroidUtilities.displaySize.x); + cell2.getTextView().setPadding(0, dp(10), 0, dp(17)); + } + cell3 = cell2; + } else if (viewType == VIEW_TYPE_SHADOW_COLLAPSE_BUTTON) { + CollapseTextCell btn = (CollapseTextCell) holder.itemView; + btn.set(item.animatedText, item.collapsed); + if (item.accent) { + btn.setColor(Theme.key_windowBackgroundWhiteBlueText4); + } else if (item.red) { + btn.setColor(Theme.key_text_RedRegular); + } else { + btn.setColor(Theme.key_windowBackgroundWhiteBlackText); + } + cell3 = btn; } final boolean prev = prevItem != null && !isShadow(prevItem.viewType); final boolean next = nextItem != null && !isShadow(nextItem.viewType); @@ -501,10 +616,15 @@ public class UniversalAdapter extends AdapterWithDiffUtils { } else { drawable = R.drawable.field_carret_empty; } - if (item.backgroundKey != 0) { - cell2.setBackgroundColor(getThemedColor(item.backgroundKey)); + Drawable shadowDrawable = Theme.getThemedDrawableByKey(context, drawable, Theme.key_windowBackgroundGrayShadow, resourcesProvider); + if (dialog) { + cell3.setBackground(new LayerDrawable(new Drawable[]{ + new ColorDrawable(getThemedColor(Theme.key_dialogBackgroundGray)), + shadowDrawable + })); + } else { + cell3.setBackground(shadowDrawable); } - cell2.setBackground(Theme.getThemedDrawableByKey(context, drawable, Theme.key_windowBackgroundGrayShadow, resourcesProvider)); break; case VIEW_TYPE_CUSTOM: FrameLayout frameLayout = (FrameLayout) holder.itemView; @@ -608,8 +728,105 @@ public class UniversalAdapter extends AdapterWithDiffUtils { TextRightIconCell textCell = (TextRightIconCell) holder.itemView; textCell.setTextAndIcon(item.text, item.iconResId); textCell.setDivider(divider); - if (item.backgroundKey != 0) { - textCell.setBackgroundColor(getThemedColor(item.backgroundKey)); + textCell.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + break; + case VIEW_TYPE_GRAY_SECTION: + GraySectionCell sectionCell = (GraySectionCell) holder.itemView; + if (TextUtils.equals(sectionCell.getText(), item.text)) { + sectionCell.setRightText(item.subtext, true, item.clickCallback); + } else { + sectionCell.setText(item.text, item.subtext, item.clickCallback); + } + break; + case VIEW_TYPE_PROFILE_CELL: + ProfileSearchCell profileCell = (ProfileSearchCell) holder.itemView; + Object object = item.object; + CharSequence s = ""; + if (item.withUsername) { + String username = null; + if (object instanceof TLRPC.User) { + username = UserObject.getPublicUsername((TLRPC.User) object); + } else if (object instanceof TLRPC.Chat) { + username = ChatObject.getPublicUsername((TLRPC.Chat) object); + } + if (username != null) { + s += "@" + username; + } + } + String title = ""; + if (object instanceof TLRPC.Chat) { + TLRPC.Chat chat = (TLRPC.Chat) object; + if (chat.participants_count != 0) { + String membersString; + if (ChatObject.isChannel(chat) && !chat.megagroup) { + membersString = LocaleController.formatPluralStringComma("Subscribers", chat.participants_count, ' '); + } else { + membersString = LocaleController.formatPluralStringComma("Members", chat.participants_count, ' '); + } + if (s instanceof SpannableStringBuilder) { + ((SpannableStringBuilder) s).append(", ").append(membersString); + } else if (!TextUtils.isEmpty(s)) { + s = TextUtils.concat(s, ", ", membersString); + } else { + s = membersString; + } + } + title = chat.title; + } else if (object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) object; + // add status text + title = UserObject.getUserName(user); + } + profileCell.setData(object, null, title, s, false, false); + profileCell.useSeparator = divider; + break; + case VIEW_TYPE_SEARCH_MESSAGE: + DialogCell dialogCell = (DialogCell) holder.itemView; + MessageObject messageObject = null; + if (item.object instanceof MessageObject) { + messageObject = (MessageObject) item.object; + } + dialogCell.useSeparator = divider; + if (messageObject == null) { + dialogCell.setDialog(0, null, 0, false, false); + } else { + dialogCell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, false, false); + } + break; + case VIEW_TYPE_FLICKER: + FlickerLoadingView flickerLoadingView = (FlickerLoadingView) holder.itemView; + flickerLoadingView.setViewType(item.intValue); + break; + case VIEW_TYPE_ROUND_CHECKBOX: + case VIEW_TYPE_ROUND_GROUP_CHECKBOX: + case VIEW_TYPE_USER_GROUP_CHECKBOX: + CheckBoxCell checkBoxCell = (CheckBoxCell) holder.itemView; + checkBoxCell.setPad(item.pad); + checkBoxCell.setText(item.text, "", item.checked, divider, checkBoxCell.itemId == item.id); + checkBoxCell.itemId = item.id; + checkBoxCell.setIcon(item.locked ? R.drawable.permission_locked : 0); + if (viewType == VIEW_TYPE_USER_GROUP_CHECKBOX || viewType == VIEW_TYPE_ROUND_GROUP_CHECKBOX) { + checkBoxCell.setCollapseButton(item.collapsed, item.animatedText, item.clickCallback); + } + break; + case VIEW_TYPE_USER_CHECKBOX: + CheckBoxCell userCheckBoxCell = (CheckBoxCell) holder.itemView; + userCheckBoxCell.setPad(item.pad); + userCheckBoxCell.setUserOrChat((TLObject) item.object); + userCheckBoxCell.setChecked(item.checked, userCheckBoxCell.itemId == item.id); + userCheckBoxCell.itemId = item.id; + userCheckBoxCell.setNeedDivider(divider); + break; + case VIEW_TYPE_SWITCH: + case VIEW_TYPE_EXPANDABLE_SWITCH: + TextCheckCell2 switchCell = (TextCheckCell2) holder.itemView; + switchCell.setTextAndCheck(item.text.toString(), item.checked, divider, switchCell.id == item.id); + switchCell.id = item.id; + switchCell.setIcon(item.locked ? R.drawable.permission_locked : 0); + if (viewType == VIEW_TYPE_EXPANDABLE_SWITCH) { + switchCell.setCollapseArrow(item.animatedText.toString(), item.collapsed, () -> { + item.clickCallback.onClick(switchCell); + }); } break; } @@ -674,7 +891,15 @@ public class UniversalAdapter extends AdapterWithDiffUtils { viewType == VIEW_TYPE_QUICK_REPLY || viewType == VIEW_TYPE_BUSINESS_LINK || viewType == VIEW_TYPE_TRANSACTION || - viewType == VIEW_TYPE_RADIO_USER + viewType == VIEW_TYPE_RADIO_USER || + viewType == VIEW_TYPE_PROFILE_CELL || + viewType == VIEW_TYPE_SEARCH_MESSAGE || + viewType == VIEW_TYPE_ROUND_CHECKBOX || + viewType == VIEW_TYPE_USER_GROUP_CHECKBOX || + viewType == VIEW_TYPE_USER_CHECKBOX || + viewType == VIEW_TYPE_ROUND_GROUP_CHECKBOX || + viewType == VIEW_TYPE_SWITCH || + viewType == VIEW_TYPE_EXPANDABLE_SWITCH ) && (item == null || item.enabled); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java index 329644ee6..54fec81b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java @@ -44,32 +44,6 @@ public abstract class UniversalFragment extends BaseFragment { }); FrameLayout contentView = new SizeNotifierFrameLayout(context) { -// private AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { -// @Override -// protected void onTransitionStart(boolean keyboardVisible, int contentHeight) {} -// @Override -// protected void onTransitionEnd() {} -// @Override -// protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { -// if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { -// return; -// } -// actionBar.setTranslationY(y); -// } -// }; -// -// @Override -// protected void onAttachedToWindow() { -// super.onAttachedToWindow(); -// adjustPanLayoutHelper.onAttach(); -// } -// -// @Override -// protected void onDetachedFromWindow() { -// super.onDetachedFromWindow(); -// adjustPanLayoutHelper.onDetach(); -// } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java index 40f6dda0f..95fa8e4ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java @@ -306,6 +306,12 @@ public class VideoSeekPreviewImage extends View { }); } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setPivotY(getMeasuredHeight()); + } + public boolean isReady() { return ready; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index e90a75143..f37d5757a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -33,6 +33,7 @@ import android.text.TextPaint; import android.text.TextUtils; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -62,6 +63,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.WebFile; import org.telegram.tgnet.ConnectionsManager; @@ -131,7 +133,11 @@ public class ContentPreviewViewer { } - default void newStickerPackSelected(CharSequence name, String emoji) { + default void newStickerPackSelected(CharSequence name, String emoji, Utilities.Callback whenDone) { + + } + + default void setIntroSticker(String emoji) { } @@ -169,6 +175,10 @@ public class ContentPreviewViewer { } + default boolean canDeleteSticker(TLRPC.Document document) { + return false; + } + default void deleteSticker(TLRPC.Document document) { } @@ -185,6 +195,14 @@ public class ContentPreviewViewer { return false; } + default boolean isSettingIntroSticker() { + return false; + } + + default void sendIntroSticker() { + + } + default String getQuery(boolean isGif) { return null; } @@ -257,6 +275,7 @@ public class ContentPreviewViewer { private ContentPreviewViewerDelegate delegate; private boolean isPhotoEditor; private boolean isStickerEditor; + private ArrayList selectedEmojis; private boolean isRecentSticker; @@ -270,9 +289,9 @@ public class ContentPreviewViewer { private WindowManager.LayoutParams windowLayoutParams; private FrameLayout windowView; private FrameLayoutDrawer containerView; - private ImageReceiver centerImage = new ImageReceiver(); + public ImageReceiver centerImage = new ImageReceiver(); private ImageReceiver effectImage = new ImageReceiver(); - private PaintingOverlay paintingOverlay; + public PaintingOverlay paintingOverlay; private Path paintingOverlayClipPath; private boolean isVisible = false; private float showProgress; @@ -281,6 +300,7 @@ public class ContentPreviewViewer { private int keyboardHeight = AndroidUtilities.dp(200); private Drawable slideUpDrawable; private boolean menuVisible; + private View popupLayout; private float blurProgress; private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private UnlockPremiumView unlockPremiumView; @@ -308,18 +328,26 @@ public class ContentPreviewViewer { ArrayList icons = new ArrayList<>(); if (stickerSetForCustomSticker == null) { - items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); - icons.add(R.drawable.msg_send); - actions.add(0); + if (delegate != null && delegate.isSettingIntroSticker()) { + items.add(LocaleController.getString(R.string.SetIntroSticker)); + icons.add(R.drawable.menu_sticker_add); + actions.add(0); + } else { + items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); + icons.add(R.drawable.msg_send); + actions.add(0); - items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - icons.add(R.drawable.msg_fave); - actions.add(1); + items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); + icons.add(R.drawable.msg_fave); + actions.add(1); + } } - items.add(LocaleController.getString(delegate != null && delegate.isReplacedSticker() ? R.string.StickersReplaceSticker : R.string.AddToStickerPack)); - icons.add(delegate != null && delegate.isReplacedSticker() ? R.drawable.msg_replace : R.drawable.menu_sticker_add); - actions.add(2); + if (delegate == null || !delegate.isSettingIntroSticker()) { + items.add(LocaleController.getString(delegate != null && delegate.isReplacedSticker() ? R.string.StickersReplaceSticker : R.string.AddToStickerPack)); + icons.add(delegate != null && delegate.isReplacedSticker() ? R.drawable.msg_replace : R.drawable.menu_sticker_add); + actions.add(2); + } ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(parentActivity, true, false, resourcesProvider); backCell.setItemHeight(44); @@ -339,18 +367,25 @@ public class ContentPreviewViewer { reactionsWindow.dismiss(); } if (stickerSetCovered instanceof TLRPC.TL_stickerSetNoCovered) { - StickersDialogs.showNameEditorDialog(null, resourcesProvider, containerView.getContext(), arg -> { - delegate.newStickerPackSelected(arg, reactionsLayout.getSelectedEmoji()); - if (popupWindow != null) { - popupWindow.dismiss(); + StickersDialogs.showNameEditorDialog(null, resourcesProvider, containerView.getContext(), (text, whenDone) -> { + if (delegate != null) { + delegate.newStickerPackSelected(text, TextUtils.join("", selectedEmojis), whenDone != null ? success -> { + whenDone.run(success); + if (success) { + dismissPopupWindow(); + } + } : null); + if (whenDone == null) { + dismissPopupWindow(); + } } }); return; } - delegate.stickerSetSelected(stickerSetCovered.set, reactionsLayout.getSelectedEmoji()); - if (popupWindow != null) { - popupWindow.dismiss(); + if (delegate != null) { + delegate.stickerSetSelected(stickerSetCovered.set, TextUtils.join("", selectedEmojis)); } + dismissPopupWindow(); }); backContainer.addView(backCell); linearLayout.addView(backContainer); @@ -368,20 +403,24 @@ public class ContentPreviewViewer { listView.getAdapter().notifyDataSetChanged(); previewMenu.getSwipeBack().openForeground(1); } else { - delegate.stickerSetSelected(stickerSetForCustomSticker.set, reactionsLayout.getSelectedEmoji()); - if (popupWindow != null) { - popupWindow.dismiss(); + if (delegate != null) { + delegate.stickerSetSelected(stickerSetForCustomSticker.set, TextUtils.join("", selectedEmojis)); } + dismissPopupWindow(); } } else { - if (actions.get(which) == 1) { - delegate.addToFavoriteSelected(reactionsLayout.getSelectedEmoji()); - } else if (actions.get(which) == 0) { - delegate.sendSticker(); - } - if (popupWindow != null) { - popupWindow.dismiss(); + if (delegate != null) { + if (actions.get(which) == 1) { + delegate.addToFavoriteSelected(TextUtils.join("", selectedEmojis)); + } else if (actions.get(which) == 0) { + if (delegate.isSettingIntroSticker()) { + delegate.setIntroSticker(TextUtils.join("", selectedEmojis)); + } else { + delegate.sendSticker(); + } + } } + dismissPopupWindow(); } }; for (int i = 0; i < items.size(); i++) { @@ -395,27 +434,27 @@ public class ContentPreviewViewer { previewMenu.addViewToSwipeBack(linearLayout); backContainer.setOnClickListener(view -> previewMenu.getSwipeBack().closeForeground()); - popupWindow = new ActionBarPopupWindow(previewMenu, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { - @Override - public void dismiss() { - super.dismiss(); - popupWindow = null; - menuVisible = false; - if (closeOnDismiss) { - close(); - } - } - }; - popupWindow.setPauseNotifications(true); - popupWindow.setDismissAnimationDuration(100); - popupWindow.setScaleOut(true); - popupWindow.setOutsideTouchable(false); - popupWindow.setClippingEnabled(false); - popupWindow.setAnimationStyle(R.style.PopupContextAnimation); - popupWindow.setFocusable(false); - previewMenu.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); - popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - popupWindow.getContentView().setFocusableInTouchMode(true); +// popupWindow = new ActionBarPopupWindow(previewMenu, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { +// @Override +// public void dismiss() { +// super.dismiss(); +// popupWindow = null; +// menuVisible = false; +// if (closeOnDismiss) { +// close(); +// } +// } +// }; +// popupWindow.setPauseNotifications(true); +// popupWindow.setDismissAnimationDuration(100); +// popupWindow.setScaleOut(true); +// popupWindow.setOutsideTouchable(false); +// popupWindow.setClippingEnabled(false); +// popupWindow.setAnimationStyle(R.style.PopupContextAnimation); +// popupWindow.setFocusable(false); +// previewMenu.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); +// popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); +// popupWindow.getContentView().setFocusableInTouchMode(true); int insets = 0; int top; @@ -428,7 +467,16 @@ public class ContentPreviewViewer { int size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) / 1.8f); int y = (int) (moveY + Math.max(size / 2 + top, (containerView.getHeight() - insets - keyboardHeight) / 2) + size / 2); y += AndroidUtilities.dp(24 + 60); - popupWindow.showAtLocation(containerView, 0, (int) ((containerView.getMeasuredWidth() - previewMenu.getMeasuredWidth()) / 2f), y); + containerView.addView(previewMenu, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, (float) (y / AndroidUtilities.density), 0, 0)); +// popupWindow.showAtLocation(containerView, 0, x, y); + popupLayout = previewMenu; + popupLayout.setTranslationY(-dp(12)); + popupLayout.setAlpha(0f); + popupLayout.setScaleX(.8f); + popupLayout.setScaleY(.8f); + popupLayout.setPivotY(0); + popupLayout.setPivotX(popupLayout.getMeasuredWidth() / 2f); + popupLayout.animate().translationY(0).alpha(1f).scaleX(1f).scaleY(1f).setDuration(320).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); showEmojiSelectorForStickers(); menuVisible = true; containerView.invalidate(); @@ -486,14 +534,16 @@ public class ContentPreviewViewer { final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); TLRPC.TL_messages_stickerSet stickerSet = mediaDataController.getStickerSet(currentStickerSet, true); if (stickerSet != null && stickerSet.set.creator && !StickersAlert.DISABLE_STICKER_EDITOR) { - if (delegate != null && delegate.canEditSticker() && !stickerSet.set.emojis && !stickerSet.set.masks && MessageObject.isStaticStickerDocument(currentDocument)) { + if (delegate != null && delegate.canEditSticker() && !stickerSet.set.emojis && !stickerSet.set.masks) { items.add(LocaleController.getString(R.string.EditSticker)); icons.add(R.drawable.msg_edit); actions.add(7); } - items.add(LocaleController.getString(R.string.DeleteSticker)); - icons.add(R.drawable.msg_delete); - actions.add(8); + if (delegate != null && delegate.canDeleteSticker(currentDocument)) { + items.add(LocaleController.getString(R.string.DeleteSticker)); + icons.add(R.drawable.msg_delete); + actions.add(8); + } } } @@ -538,9 +588,7 @@ public class ContentPreviewViewer { } else if (actions.get(which) == 8) { delegate.deleteSticker(currentDocument); } - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); } }; @@ -681,9 +729,7 @@ public class ContentPreviewViewer { } else if (action == 5) { MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_FAVE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), inFavs); } - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); }; for (int i = 0; i < items.size(); i++) { @@ -818,9 +864,7 @@ public class ContentPreviewViewer { ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; AlertsCreator.createScheduleDatePickerDialog(parentActivity, stickerPreviewViewerDelegate.getDialogId(), (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendGif(document != null ? document : result, parent, notify, scheduleDate), resourcesProvider); } - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); }; for (int i = 0; i < items.size(); i++) { @@ -920,25 +964,37 @@ public class ContentPreviewViewer { reactionsLayoutContainer = new FrameLayout(containerView.getContext()); reactionsLayoutContainer.addView(reactionsLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 72 + 22 + 22, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 0)); containerView.addView(reactionsLayoutContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 100, 0, 0)); - reactionsLayout.setMessage(null, null); } + reactionsLayout.setSelectedEmojis(selectedEmojis); reactionsLayout.setDelegate((view, visibleReaction, longpress, addToRecent) -> { + if (visibleReaction == null) return; CustomEmojiReactionsWindow reactionsWindow = reactionsLayout.getReactionsWindow(); - if (reactionsWindow != null && reactionsWindow.isShowing()) { - reactionsLayout.setSelectedReactionInclusive(visibleReaction); - reactionsWindow.getSelectAnimatedEmojiDialog().setSelectedReaction(visibleReaction); - AndroidUtilities.runOnUIThread(reactionsWindow::dismiss, 200); + if (selectedEmojis.contains(visibleReaction.emojicon)) { + if (selectedEmojis.size() <= 1) { + return; + } + selectedEmojis.remove(visibleReaction.emojicon); } else { - reactionsLayout.setSelectedReactionInclusive(visibleReaction); + selectedEmojis.add(visibleReaction.emojicon); + if (selectedEmojis.size() > 7) { + selectedEmojis.remove(0); + } + } + reactionsLayout.setSelectedEmojis(selectedEmojis); + if (reactionsWindow != null) { + reactionsLayout.setMessage(null, null, false); + if (reactionsWindow.getSelectAnimatedEmojiDialog() != null) { + reactionsWindow.getSelectAnimatedEmojiDialog().setSelectedReactions(selectedEmojis); + reactionsWindow.getSelectAnimatedEmojiDialog().setRecentReactions(reactionsLayout.allReactionsList); + } + reactionsWindow.dismiss(); } }); - if (!reactionsLayout.getVisibleReactionsList().isEmpty()) { - reactionsLayout.setSelectedReaction(reactionsLayout.getVisibleReactionsList().get(0)); - } + reactionsLayout.setMessage(null, null, false); reactionsLayoutContainer.setScaleY(0.6f); reactionsLayoutContainer.setScaleX(0.6f); reactionsLayoutContainer.setAlpha(0f); - AndroidUtilities.runOnUIThread(() -> reactionsLayoutContainer.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start(), 10); + AndroidUtilities.runOnUIThread(() -> reactionsLayoutContainer.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(), 10); } private void showUnlockPremiumView() { @@ -1133,9 +1189,7 @@ public class ContentPreviewViewer { clearsInputField = false; menuVisible = false; closeOnDismiss = false; - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); AndroidUtilities.updateViewVisibilityAnimated(unlockPremiumView, false); if (currentPreviewCell instanceof StickerEmojiCell) { StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) currentPreviewCell; @@ -1143,7 +1197,7 @@ public class ContentPreviewViewer { stickerEmojiCell.setScaled(true); } else if (currentPreviewCell instanceof StickerCell) { StickerCell stickerCell = (StickerCell) currentPreviewCell; - open(stickerCell.getSticker(), null, null, delegate != null ? delegate.getQuery(false) : null, null, contentType, false, stickerCell.getParentObject(), resourcesProvider); + open(stickerCell.getSticker(), null, MessageObject.findAnimatedEmojiEmoticon(stickerCell.getSticker(), null, currentAccount), delegate != null ? delegate.getQuery(false) : null, null, contentType, false, stickerCell.getParentObject(), resourcesProvider); stickerCell.setScaled(true); clearsInputField = stickerCell.isClearsInputField(); } else if (currentPreviewCell instanceof ContextLinkCell) { @@ -1389,7 +1443,20 @@ public class ContentPreviewViewer { slideUpDrawable = parentActivity.getResources().getDrawable(R.drawable.preview_arrow); - windowView = new FrameLayout(activity); + windowView = new FrameLayout(activity) { + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == 1) { + if (isStickerEditor || menuVisible) { + closeWithMenu(); + } else { + close(); + } + return true; + } + return super.dispatchKeyEvent(event); + } + }; windowView.setFocusable(true); windowView.setFocusableInTouchMode(true); if (Build.VERSION.SDK_INT >= 21) { @@ -1428,7 +1495,6 @@ public class ContentPreviewViewer { return true; }); - SharedPreferences sharedPreferences = MessagesController.getInstance(currentAccount).getGlobalEmojiSettings(); keyboardHeight = sharedPreferences.getInt("kbd_height", AndroidUtilities.dp(200)); @@ -1500,14 +1566,20 @@ public class ContentPreviewViewer { break; } } - if (contentType == CONTENT_TYPE_EMOJI && emojiPath != null) { + if (emojiPath != null) { CharSequence emoji = Emoji.replaceEmoji(emojiPath, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(500), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + emoji = TextUtils.ellipsize(emoji, textPaint, dp(200), TextUtils.TruncateAt.END); + emoji = AndroidUtilities.replaceCharSequence("\u2026", emoji, ""); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(200), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } if ((newSet != null || contentType == CONTENT_TYPE_EMOJI) && (delegate == null || delegate.needMenu())) { AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); } + TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSet(newSet, true); + if (stickerSet != null && stickerSet.documents.isEmpty()) { + newSet = null; + } currentStickerSet = newSet; TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (MessageObject.isVideoStickerDocument(document)) { @@ -1528,7 +1600,9 @@ public class ContentPreviewViewer { if (attribute instanceof TLRPC.TL_documentAttributeSticker) { if (!TextUtils.isEmpty(attribute.alt)) { CharSequence emoji = Emoji.replaceEmoji(attribute.alt, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(500), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + emoji = TextUtils.ellipsize(emoji, textPaint, dp(200), TextUtils.TruncateAt.END); + emoji = AndroidUtilities.replaceCharSequence("\u2026", emoji, ""); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(200), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); break; } } @@ -1545,7 +1619,9 @@ public class ContentPreviewViewer { } if (emojiPath != null) { CharSequence emoji = Emoji.replaceEmoji(emojiPath, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(500), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + emoji = TextUtils.ellipsize(emoji, textPaint, dp(200), TextUtils.TruncateAt.END); + emoji = AndroidUtilities.replaceCharSequence("\u2026", emoji, ""); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(200), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } if (delegate.needMenu()) { AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); @@ -1632,10 +1708,7 @@ public class ContentPreviewViewer { } } menuVisible = false; - if (popupWindow != null) { - popupWindow.dismiss(); - popupWindow = null; - } + dismissPopupWindow(); close(); } @@ -1819,9 +1892,9 @@ public class ContentPreviewViewer { } if (stickerEmojiLayout != null) { if (drawEffect) { - canvas.translate(-AndroidUtilities.dp(250), -effectImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + canvas.translate(-stickerEmojiLayout.getWidth() / 2f, -effectImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); } else { - canvas.translate(-AndroidUtilities.dp(250), -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + canvas.translate(-stickerEmojiLayout.getWidth() / 2f, -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); } textPaint.setAlpha((int) (0xFF * showProgress)); stickerEmojiLayout.draw(canvas); @@ -1921,7 +1994,7 @@ public class ContentPreviewViewer { return false; } - public void showCustomStickerActions(String path, VideoEditedInfo videoEditedInfo, View view, ContentPreviewViewerDelegate delegate) { + public void showCustomStickerActions(String path, VideoEditedInfo videoEditedInfo, View view, ArrayList selectedEmojis, ContentPreviewViewerDelegate delegate) { Activity activity = AndroidUtilities.findActivity(view.getContext()); if (activity == null) { return; @@ -1931,13 +2004,14 @@ public class ContentPreviewViewer { SendMessagesHelper.ImportingSticker sticker = new SendMessagesHelper.ImportingSticker(); sticker.path = path; sticker.videoEditedInfo = videoEditedInfo; + this.selectedEmojis = selectedEmojis; open(null, sticker, null, null, null, CONTENT_TYPE_CUSTOM_STIKER, false, null, new DarkThemeResourceProvider()); AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); AndroidUtilities.runOnUIThread(showSheetRunnable, 16); } private void getMyStickersRemote(TLRPC.TL_messages_getMyStickers request, List resultList) { - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (error != null) { return; } @@ -1945,7 +2019,12 @@ public class ContentPreviewViewer { TLRPC.TL_messages_myStickers myStickers = (TLRPC.TL_messages_myStickers) response; for (TLRPC.StickerSetCovered set : myStickers.sets) { if (!set.set.emojis && !set.set.masks) { - resultList.add(set); + TLRPC.TL_inputStickerSetID inputStickerSetID = new TLRPC.TL_inputStickerSetID(); + inputStickerSetID.id = set.set.id; + TLRPC.TL_messages_stickerSet fullSet = MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSetID, true); + if (fullSet == null || fullSet.documents.size() < StickersAlert.STICKERS_MAX_COUNT) { + resultList.add(set); + } } } if (myStickers.sets.size() == request.limit) { @@ -2065,4 +2144,18 @@ public class ContentPreviewViewer { } } } + + private void dismissPopupWindow() { + if (popupWindow != null) { + popupWindow.dismiss(); + popupWindow = null; + } else if (popupLayout != null) { + popupLayout.animate().alpha(0).scaleX(.8f).scaleY(.8f).translationY(dp(-12)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + popupLayout = null; + menuVisible = false; + if (closeOnDismiss) { + close(); + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 31cd9a684..bcd7d5744 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -31,6 +31,7 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Outline; @@ -120,11 +121,13 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.XiaomiUtilities; +import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_chatlists; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -172,6 +175,7 @@ import org.telegram.ui.Components.ArchiveHelp; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BlurredRecyclerView; +import org.telegram.ui.Stories.StealthModeAlert; import org.telegram.ui.bots.BotWebViewSheet; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; @@ -4386,6 +4390,28 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } }); + searchViewPager.channelsSearchListView.setOnItemClickListener((view, position, x, y) -> { + Object obj = searchViewPager.channelsSearchAdapter.getObject(position); + if (obj instanceof TLRPC.Chat) { + Bundle args = new Bundle(); + args.putLong("chat_id", ((TLRPC.Chat) obj).id); + ChatActivity chatActivity = new ChatActivity(args); + chatActivity.setNextChannels(searchViewPager.channelsSearchAdapter.getNextChannels(position)); + presentFragment(chatActivity); + } else if (obj instanceof MessageObject) { + MessageObject msg = (MessageObject) obj; + Bundle args = new Bundle(); + if (msg.getDialogId() >= 0) { + args.putLong("user_id", msg.getDialogId()); + } else { + args.putLong("chat_id", -msg.getDialogId()); + } + args.putInt("message_id", msg.getId()); + ChatActivity chatActivity = new ChatActivity(args); + presentFragment(highlightFoundQuote(chatActivity, msg)); + } + }); + searchViewPager.searchListView.setOnItemClickListener((view, position, x, y) -> { if (view instanceof ProfileSearchCell && ((ProfileSearchCell) view).isBlocked()) { showPremiumBlockedToast(view, ((ProfileSearchCell) view).getDialogId()); @@ -4943,6 +4969,22 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. TLRPC.Chat chat = getMessagesController().getChat(-dialogId); final String key = NotificationsController.getSharedPrefKey(dialogId, 0); boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId); + boolean isPremiumBlocked = MessagesController.getInstance(currentAccount).premiumFeaturesBlocked(); + boolean isPremium = UserConfig.getInstance(currentAccount).isPremium(); + boolean isUnread = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().hasUnreadStories(dialogId); + CombinedDrawable stealthModeLockedDrawable = null; + if (!isPremiumBlocked && dialogId > 0 && !isPremium) { + Drawable lockIcon = ContextCompat.getDrawable(getContext(), R.drawable.msg_gallery_locked2); + if (lockIcon != null) { + Drawable stealthDrawable = ContextCompat.getDrawable(getContext(), R.drawable.msg_stealth_locked); + if (stealthDrawable != null) { + stealthDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon, resourceProvider), PorterDuff.Mode.MULTIPLY)); + } + + lockIcon.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); + stealthModeLockedDrawable = new CombinedDrawable(stealthDrawable, lockIcon); + } + } filterOptions .addIf(dialogId > 0, R.drawable.msg_discussion, LocaleController.getString("SendMessage", R.string.SendMessage), () -> { presentFragment(ChatActivity.of(dialogId)); @@ -4972,6 +5014,35 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. name = name.substring(0, index); } BulletinFactory.of(DialogsActivity.this).createUsersBulletin(Arrays.asList(user), AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsStoryUnmutedHint", R.string.NotificationsStoryUnmutedHint, name))).show(); + }).makeMultiline(false).addIf(!isPremiumBlocked && dialogId > 0 && isPremium && isUnread, R.drawable.msg_stories_stealth2, LocaleController.getString(R.string.ViewAnonymously), () -> { + TL_stories.TL_storiesStealthMode stealthMode = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().getStealthMode(); + if (stealthMode != null && ConnectionsManager.getInstance(currentAccount).getCurrentTime() < stealthMode.active_until_date) { + if (view instanceof StoryCell) { + dialogStoriesCell.openStoryForCell((StoryCell) view); + } + } else { + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), 0, StealthModeAlert.TYPE_FROM_DIALOGS, resourceProvider); + stealthModeAlert.setListener(isStealthModeEnabled -> { + if (view instanceof StoryCell) { + dialogStoriesCell.openStoryForCell((StoryCell) view); + if (isStealthModeEnabled) { + AndroidUtilities.runOnUIThread(StealthModeAlert::showStealthModeEnabledBulletin, 500); + } + } + }); + showDialog(stealthModeAlert); + } + }).makeMultiline(false).addIf(!isPremiumBlocked && dialogId > 0 && !isPremium && isUnread, R.drawable.msg_stories_stealth2, stealthModeLockedDrawable, LocaleController.getString(R.string.ViewAnonymously), () -> { + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), 0, StealthModeAlert.TYPE_FROM_DIALOGS, resourceProvider); + stealthModeAlert.setListener(isStealthModeEnabled -> { + if (view instanceof StoryCell) { + dialogStoriesCell.openStoryForCell((StoryCell) view); + if (isStealthModeEnabled) { + AndroidUtilities.runOnUIThread(StealthModeAlert::showStealthModeEnabledBulletin, 500); + } + } + }); + showDialog(stealthModeAlert); }).makeMultiline(false).addIf(!isArchive(), R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), () -> { toggleArciveForStory(dialogId); }).makeMultiline(false).addIf(isArchive(), R.drawable.msg_unarchive, LocaleController.getString("UnarchiveStories", R.string.UnarchiveStories), () -> { @@ -5719,7 +5790,23 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } authHintCell.set(DialogsActivity.this, currentAccount); updateAuthHintCellVisibility(true); - } else if (folderId == 0 && !getMessagesController().premiumPurchaseBlocked() && BirthdayController.getInstance(currentAccount).contains()) { + } else if (folderId == 0 && MessagesController.getInstance(currentAccount).pendingSuggestions.contains("PREMIUM_GRACE")) { + dialogsHintCellVisible = true; + dialogsHintCell.setVisibility(View.VISIBLE); + dialogsHintCell.setCompact(true); + dialogsHintCell.setOnClickListener(v -> { + Browser.openUrl(getContext(), getMessagesController().premiumManageSubscriptionUrl); + }); + dialogsHintCell.setText(Emoji.replaceWithRestrictedEmoji(LocaleController.getString(R.string.GraceTitle), dialogsHintCell.titleView, this::updateDialogsHint), LocaleController.getString(R.string.GraceMessage)); + dialogsHintCell.setOnCloseListener(v -> { + MessagesController.getInstance(currentAccount).removeSuggestion(0, "PREMIUM_GRACE"); + ChangeBounds transition = new ChangeBounds(); + transition.setDuration(200); + TransitionManager.beginDelayedTransition((ViewGroup) dialogsHintCell.getParent(), transition); + updateDialogsHint(); + }); + updateAuthHintCellVisibility(false); + } else if (folderId == 0 && !getMessagesController().premiumPurchaseBlocked() && BirthdayController.getInstance(currentAccount).contains() && !getMessagesController().dismissedSuggestions.contains("BIRTHDAY_CONTACTS_TODAY")) { BirthdayController.BirthdayState state = BirthdayController.getInstance(currentAccount).getState(); ArrayList users = state.today; dialogsHintCellVisible = true; @@ -5739,6 +5826,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. ); dialogsHintCell.setOnCloseListener(v -> { BirthdayController.getInstance(currentAccount).hide(); + MessagesController.getInstance(currentAccount).removeSuggestion(0, "BIRTHDAY_CONTACTS_TODAY"); ChangeBounds transition = new ChangeBounds(); transition.setDuration(200); TransitionManager.beginDelayedTransition((ViewGroup) dialogsHintCell.getParent(), transition); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java index 3ffd94b8f..89dbe3ab5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java @@ -390,9 +390,9 @@ public class EditWidgetActivity extends BaseFragment { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; if (Build.VERSION.SDK_INT >= 18) { - innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question.text); } else { - innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question.text); } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { @@ -454,7 +454,7 @@ public class EditWidgetActivity extends BaseFragment { } else { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; - messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; + messageString = "\uD83D\uDCCA " + mediaPoll.poll.question.text; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; } else if (message.type == MessageObject.TYPE_MUSIC) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java index 76907e2e5..fc3353c3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java @@ -65,14 +65,23 @@ public class FragmentUsernameBottomSheet { layout.setOrientation(LinearLayout.VERTICAL); layout.setPadding(dp(16), 0, dp(16), 0); + FrameLayout imageContainerView = new FrameLayout(context); + imageContainerView.setBackground(Theme.createCircleDrawable(dp(80), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider))); + layout.addView(imageContainerView, LayoutHelper.createLinear(80, 80, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 16)); + RLottieImageView imageView = new RLottieImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); int sz = type == TYPE_USERNAME ? 70 : 78; imageView.setAnimation(type == TYPE_USERNAME ? R.raw.fragment_username : R.raw.fragment_phone, sz, sz); imageView.playAnimation(); imageView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); - imageView.setBackground(Theme.createCircleDrawable(dp(80), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider))); - layout.addView(imageView, LayoutHelper.createLinear(80, 80, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 16)); + if (type == TYPE_USERNAME) { + imageView.setScaleX(0.86f); + imageView.setScaleY(0.86f); + } else { + imageView.setTranslationY(dp(2)); + } + imageContainerView.addView(imageView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); final String ownerName; if (owner instanceof TLRPC.User) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java index ca3c06340..fa4926838 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java @@ -448,7 +448,7 @@ public abstract class GradientHeaderActivity extends BaseFragment { return SimpleThemeDescription.createThemeDescriptions(this::updateColors, Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4, Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4, - Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStartGradient1, Theme.key_premiumStartGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 + Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStarGradient1, Theme.key_premiumStarGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 ); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index d73536d25..2970e8cbe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -7402,7 +7402,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter options.add(5); } - if (participant.peer.channel_id != 0 && !ChatObject.isMegagroup(currentAccount, participant.peer.channel_id)) { + if (participant.peer != null && participant.peer.channel_id != 0 && !ChatObject.isMegagroup(currentAccount, participant.peer.channel_id)) { items.add(LocaleController.getString("VoipGroupOpenChannel", R.string.VoipGroupOpenChannel)); icons.add(R.drawable.msg_msgbubble3); options.add(8); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java index 496f5f4b2..6da319cda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java @@ -90,6 +90,14 @@ public class GroupColorActivity extends ChannelColorActivity { packEmojiHintRow = rowsCount++; statusEmojiRow = rowsCount++; statusHintRow = rowsCount++; + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId); + if (chatFull != null && chatFull.can_set_stickers) { + packStickerRow = rowsCount++; + packStickerHintRow = rowsCount++; + } else { + packStickerRow = -1; + packStickerHintRow = -1; + } messagesPreviewRow = rowsCount++; wallpaperThemesRow = rowsCount++; wallpaperRow = rowsCount++; @@ -114,6 +122,16 @@ public class GroupColorActivity extends ChannelColorActivity { return R.string.GroupEmojiPackInfo; } + @Override + protected int getStickerPackStrRes() { + return R.string.GroupStickerPack; + } + + @Override + protected int getStickerPackInfoStrRes() { + return R.string.GroupStickerPackInfo; + } + @Override protected int getProfileInfoStrRes() { return R.string.GroupProfileInfo; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 89f4189c0..8d75f85b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -644,10 +644,16 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else if (id == 15) { showSelectStatusDialog(); } else if (id == 16) { + drawerLayoutContainer.closeDrawer(true); + Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putBoolean("my_profile", true); + presentFragment(new ProfileActivity(args, null)); + } else if (id == 17) { + drawerLayoutContainer.closeDrawer(true); Bundle args = new Bundle(); args.putLong("dialog_id", UserConfig.getInstance(currentAccount).getClientUserId()); args.putInt("type", MediaActivity.TYPE_STORIES); - drawerLayoutContainer.closeDrawer(true); presentFragment(new MediaActivity(args, null)); } } @@ -1357,7 +1363,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } DialogsActivity dialogsActivity = dialogsActivityProvider.provide(null); dialogsActivity.setSideMenu(sideMenu); - actionBarLayout.addFragmentToStack(dialogsActivity, 0); + actionBarLayout.addFragmentToStack(dialogsActivity, INavigationLayout.FORCE_ATTACH_VIEW_AS_FIRST); drawerLayoutContainer.setAllowOpenDrawer(true, false); actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); if (AndroidUtilities.isTablet()) { @@ -1711,7 +1717,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati long push_user_id = 0; long push_chat_id = 0; long[] push_story_dids = null; - int push_story_id = 0; + int push_story_id = -1; long push_topic_id = 0; int push_enc_id = 0; int push_msg_id = 0; @@ -2794,6 +2800,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati long chatId = intent.getLongExtra("chatId", 0); // Integer userIdInt = intent.getIntExtra("userId", 0); long[] storyDialogIds = intent.getLongArrayExtra("storyDialogIds"); + int storyId = intent.getIntExtra("storyId", -1); long userId = intent.getLongExtra("userId", 0); int encId = intent.getIntExtra("encId", 0); int widgetId = intent.getIntExtra("appWidgetId", 0); @@ -2806,7 +2813,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (push_msg_id == 0) { push_msg_id = intent.getIntExtra("message_id", 0); } - if (storyDialogIds != null) { + if (storyId != -1) { + NotificationCenter.getInstance(intentAccount[0]).postNotificationName(NotificationCenter.closeChats); + push_story_id = storyId; + } else if (storyDialogIds != null) { NotificationCenter.getInstance(intentAccount[0]).postNotificationName(NotificationCenter.closeChats); push_story_dids = storyDialogIds; // push_story_id = intent.getIntExtra("storyId", 0); @@ -2856,7 +2866,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } } - if (push_story_dids != null) { + if (push_story_id > 0) { + NotificationsController.getInstance(intentAccount[0]).processSeenStoryReactions(UserConfig.getInstance(intentAccount[0]).getClientUserId(), push_story_id); + openMyStory(push_story_id, true); + } else if (push_story_dids != null) { NotificationCenter.getInstance(intentAccount[0]).postNotificationName(NotificationCenter.closeChats); openStories(push_story_dids, true); } else if (push_user_id != 0) { @@ -4184,6 +4197,13 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { args.putLong("user_id", peerId); dialog_id = peerId; + if (text != null) { + String textToSet = text; + if (textToSet.startsWith("@")) { + textToSet = " " + textToSet; + } + args.putString("start_text", textToSet); + } } if (botUser != null && user != null && user.bot) { args.putString("botUser", botUser); @@ -4211,9 +4231,6 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (setAsAttachBot != null) { args.putString("attach_bot_start_command", setAsAttachBot); } - if (text != null) { - args.putString("start_text", text); - } BaseFragment lastFragment = !mainFragmentsStack.isEmpty() && voicechat == null ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; if (lastFragment == null || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, lastFragment)) { final boolean sameDialogId = lastFragment instanceof ChatActivity && ((ChatActivity) lastFragment).getDialogId() == dialog_id; @@ -7891,6 +7908,119 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati return AndroidUtilities.getLightNavigationBar(getWindow()); } + private void openMyStory(final int storyId, boolean openViews) { + final long dialogId = UserConfig.getInstance(currentAccount).getClientUserId(); + StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); + TL_stories.PeerStories peerStories = storiesController.getStories(dialogId); + TL_stories.StoryItem storyItem = null; + if (peerStories != null) { + for (int i = 0; i < peerStories.stories.size(); ++i) { + if (peerStories.stories.get(i).id == storyId) { + storyItem = peerStories.stories.get(i); + break; + } + } + if (storyItem != null) { + BaseFragment lastFragment = getLastFragment(); + if (lastFragment == null) { + return; + } + StoryViewer.PlaceProvider placeProvider = null; + if (lastFragment instanceof DialogsActivity) { + try { + placeProvider = StoriesListPlaceProvider.of(((DialogsActivity) lastFragment).dialogStoriesCell.recyclerListView); + } catch (Exception ignore) {} + } + lastFragment.getOrCreateStoryViewer().instantClose(); + ArrayList dialogIds = new ArrayList<>(); + dialogIds.add(storyItem.dialogId); + if (openViews) { + lastFragment.getOrCreateStoryViewer().showViewsAfterOpening(); + } + lastFragment.getOrCreateStoryViewer().open(this, storyItem, dialogIds, 0, null, peerStories, placeProvider, false); + return; + } + } + if (storyItem == null) { + StoriesController.StoriesList list = null; + StoriesController.StoriesList profileList = storiesController.getStoriesList(dialogId, StoriesController.StoriesList.TYPE_PINNED); + if (profileList != null) { + MessageObject msg = profileList.findMessageObject(storyId); + if (msg != null) { + storyItem = msg.storyItem; + list = profileList; + } + } + if (storyItem == null) { + StoriesController.StoriesList archiveList = storiesController.getStoriesList(dialogId, StoriesController.StoriesList.TYPE_ARCHIVE); + if (archiveList != null) { + MessageObject msg = archiveList.findMessageObject(storyId); + if (msg != null) { + storyItem = msg.storyItem; + list = archiveList; + } + } + } + if (storyItem != null && list != null) { + BaseFragment lastFragment = getLastFragment(); + if (lastFragment == null) { + return; + } + StoryViewer.PlaceProvider placeProvider = null; + if (lastFragment instanceof DialogsActivity) { + try { + placeProvider = StoriesListPlaceProvider.of(((DialogsActivity) lastFragment).dialogStoriesCell.recyclerListView); + } catch (Exception ignore) {} + } + lastFragment.getOrCreateStoryViewer().instantClose(); + ArrayList dialogIds = new ArrayList<>(); + dialogIds.add(storyItem.dialogId); + if (openViews) { + lastFragment.getOrCreateStoryViewer().showViewsAfterOpening(); + } + lastFragment.getOrCreateStoryViewer().open(this, storyItem, dialogIds, 0, list, null, placeProvider, false); + return; + } + } + TL_stories.TL_stories_getStoriesByID req = new TL_stories.TL_stories_getStoriesByID(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.id.add(storyId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TL_stories.TL_stories_stories) { + TL_stories.TL_stories_stories response = (TL_stories.TL_stories_stories) res; + TL_stories.StoryItem storyItem1 = null; + for (int i = 0; i < response.stories.size(); ++i) { + if (response.stories.get(i).id == storyId) { + storyItem1 = response.stories.get(i); + break; + } + } + if (storyItem1 != null) { + storyItem1.dialogId = dialogId; + BaseFragment lastFragment = getLastFragment(); + if (lastFragment == null) { + return; + } + StoryViewer.PlaceProvider placeProvider = null; + if (lastFragment instanceof DialogsActivity) { + try { + placeProvider = StoriesListPlaceProvider.of(((DialogsActivity) lastFragment).dialogStoriesCell.recyclerListView); + } catch (Exception ignore) {} + } + lastFragment.getOrCreateStoryViewer().instantClose(); + ArrayList dialogIds = new ArrayList<>(); + dialogIds.add(dialogId); + if (openViews) { + lastFragment.getOrCreateStoryViewer().showViewsAfterOpening(); + } + lastFragment.getOrCreateStoryViewer().open(this, storyItem1, dialogIds, 0, null, null, placeProvider, false); + return; + } + } + BulletinFactory.global().createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.StoryNotFound)).show(false); + })); + } + private void openStories(long[] dialogIds, boolean requestWhenNeeded) { boolean onlyArchived = true; for (int i = 0; i < dialogIds.length; ++i) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index f3dac656c..281975d1a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -111,6 +113,7 @@ 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 org.telegram.ui.Stories.recorder.HintView2; import java.io.File; import java.net.URLEncoder; @@ -136,7 +139,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private View shadow; private ActionBarMenuItem searchItem; private MapOverlayView overlayView; - private HintView hintView; + private HintView2 hintView; private UndoView[] undoView = new UndoView[2]; private boolean canUndo; @@ -218,7 +221,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private int locationType; - private int overScrollHeight = AndroidUtilities.displaySize.x - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(66); + private int overScrollHeight = AndroidUtilities.displaySize.x - ActionBar.getCurrentActionBarHeight() - dp(66); private final static int open_in = 1; private final static int share_live_location = 5; @@ -229,6 +232,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public final static int LOCATION_TYPE_SEND = 0; public final static int LOCATION_TYPE_SEND_WITH_LIVE = 1; + public final static int LOCATION_TYPE_LIVE = 2; 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; @@ -349,7 +353,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter addressTextView.setText(LocaleController.getString("TapToSendLocation", R.string.TapToSendLocation)); FrameLayout iconLayout = new FrameLayout(context); - iconLayout.setBackground(Theme.createCircleDrawable(AndroidUtilities.dp(36), LocationCell.getColorForIndex(location.num))); + iconLayout.setBackground(Theme.createCircleDrawable(dp(36), LocationCell.getColorForIndex(location.num))); frameLayout.addView(iconLayout, LayoutHelper.createFrame(36, 36, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 4)); BackupImageView imageView = new BackupImageView(context); @@ -416,7 +420,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter View view = entry.getValue(); Point point = projection.toScreenLocation(marker.getPosition()); view.setTranslationX(point.x - view.getMeasuredWidth() / 2); - view.setTranslationY(point.y - view.getMeasuredHeight() + AndroidUtilities.dp(22)); + view.setTranslationY(point.y - view.getMeasuredHeight() + dp(22)); } } } @@ -561,7 +565,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter FileLog.e(e); } } else if (id == share_live_location) { - openShareLiveLocation(0); + openShareLiveLocation(false, 0); } else if (id == get_directions) { openDirections(null); } @@ -696,9 +700,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter FrameLayout.LayoutParams layoutParams; if (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE) { - layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(21) + padding.top); + layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(21) + padding.top); } else { - layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(6) + padding.top); + layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(6) + padding.top); } layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; @@ -715,18 +719,18 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (messageObject == null && (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE) || messageObject != null && locationType == 3) { searchAreaButton = new SearchButton(context); - searchAreaButton.setTranslationX(-AndroidUtilities.dp(80)); - Drawable drawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + searchAreaButton.setTranslationX(-dp(80)); + Drawable drawable = Theme.createSimpleSelectorRoundRectDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); if (Build.VERSION.SDK_INT < 21) { Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.places_btn).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); - CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, AndroidUtilities.dp(2), AndroidUtilities.dp(2)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, dp(2), dp(2)); combinedDrawable.setFullsize(true); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); searchAreaButton.setStateListAnimator(animator); searchAreaButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @@ -741,7 +745,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter searchAreaButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); searchAreaButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); searchAreaButton.setGravity(Gravity.CENTER); - searchAreaButton.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0); + searchAreaButton.setPadding(dp(20), 0, dp(20), 0); mapViewClip.addView(searchAreaButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 80, 12, 80, 0)); if (locationType == 3) { searchAreaButton.setText(LocaleController.getString(R.string.OpenInMaps)); @@ -769,29 +773,29 @@ public class LocationActivity extends BaseFragment implements NotificationCenter mapTypeButton = new ActionBarMenuItem(context, null, 0, getThemedColor(Theme.key_location_actionIcon), getResourceProvider()); mapTypeButton.setClickable(true); mapTypeButton.setSubMenuOpenSide(2); - mapTypeButton.setAdditionalXOffset(AndroidUtilities.dp(10)); - mapTypeButton.setAdditionalYOffset(-AndroidUtilities.dp(10)); + mapTypeButton.setAdditionalXOffset(dp(10)); + mapTypeButton.setAdditionalYOffset(-dp(10)); mapTypeButton.addSubItem(map_list_menu_map, R.drawable.msg_map, LocaleController.getString("Map", R.string.Map), getResourceProvider()); mapTypeButton.addSubItem(map_list_menu_satellite, R.drawable.msg_satellite, LocaleController.getString("Satellite", R.string.Satellite), getResourceProvider()); mapTypeButton.addSubItem(map_list_menu_hybrid, R.drawable.msg_hybrid, LocaleController.getString("Hybrid", R.string.Hybrid), getResourceProvider()); mapTypeButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + Drawable drawable = Theme.createSimpleSelectorCircleDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(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)); + combinedDrawable.setIconSize(dp(40), dp(40)); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); mapTypeButton.setStateListAnimator(animator); mapTypeButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + outline.setOval(0, 0, dp(40), dp(40)); } }); } @@ -813,23 +817,23 @@ public class LocationActivity extends BaseFragment implements NotificationCenter }); locationButton = new ImageView(context); - drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + drawable = Theme.createSimpleSelectorCircleDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(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)); + combinedDrawable.setIconSize(dp(40), dp(40)); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); locationButton.setStateListAnimator(animator); locationButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + outline.setOval(0, 0, dp(40), dp(40)); } }); } @@ -880,23 +884,23 @@ public class LocationActivity extends BaseFragment implements NotificationCenter }); proximityButton = new ImageView(context); - drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + drawable = Theme.createSimpleSelectorCircleDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(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)); + combinedDrawable.setIconSize(dp(40), 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)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, dp(4), 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)); + outline.setOval(0, 0, dp(40), dp(40)); } }); } @@ -960,15 +964,17 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } - 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)); + hintView = new HintView2(context, HintView2.DIRECTION_TOP); + hintView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + hintView.setDuration(4000); + hintView.setJoint(1, -(12 + 13)); + hintView.setPadding(0, dp(4), 0, 0); + mapViewClip.addView(hintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 8, 12 + 50 + 44, 8, 0)); emptyView = new LinearLayout(context); emptyView.setOrientation(LinearLayout.VERTICAL); emptyView.setGravity(Gravity.CENTER_HORIZONTAL); - emptyView.setPadding(0, AndroidUtilities.dp(60 + 100), 0, 0); + emptyView.setPadding(0, dp(60 + 100), 0, 0); emptyView.setVisibility(View.GONE); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); emptyView.setOnTouchListener((v, event) -> true); @@ -990,7 +996,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter emptySubtitleTextView.setTextColor(getThemedColor(Theme.key_dialogEmptyText)); emptySubtitleTextView.setGravity(Gravity.CENTER); emptySubtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - emptySubtitleTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), 0); + emptySubtitleTextView.setPadding(dp(40), 0, dp(40), 0); emptyView.addView(emptySubtitleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 6, 0, 0)); listView = new RecyclerListView(context); @@ -1051,7 +1057,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter }); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); listView.setOnItemLongClickListener((view, position) -> { - if (locationType == 2) { + if (locationType == LOCATION_TYPE_LIVE) { Object object = adapter.getItem(position); if (object instanceof LiveLocation) { @@ -1059,7 +1065,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context); ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, getResourceProvider()); - cell.setMinimumWidth(AndroidUtilities.dp(200)); + cell.setMinimumWidth(dp(200)); cell.setTextAndIcon(LocaleController.getString("GetDirections", R.string.GetDirections), R.drawable.filled_directions); cell.setOnClickListener(e -> { openDirections(location); @@ -1083,7 +1089,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter int[] loc = new int[2]; view.getLocationInWindow(loc); - popupWindow.showAtLocation(view, Gravity.TOP, 0, loc[1] - AndroidUtilities.dp(48 + 4)); + popupWindow.showAtLocation(view, Gravity.TOP, 0, loc[1] - dp(48 + 4)); popupWindow.dimBehind(); return true; @@ -1152,12 +1158,19 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } } + } else if (locationType == LOCATION_TYPE_LIVE && getLocationController().isSharingLocation(dialogId) && adapter.getItemViewType(position) == LocationActivityAdapter.VIEW_TYPE_DELETE_LIVE_LOCATION) { + getLocationController().removeSharingLocation(dialogId); + adapter.notifyDataSetChanged(); + finishFragment(); + } else if (locationType == LOCATION_TYPE_LIVE && getLocationController().isSharingLocation(dialogId) && adapter.getItemViewType(position) == LocationActivityAdapter.VIEW_TYPE_LIVE_LOCATION) { + openShareLiveLocation(getLocationController().getSharingLocationInfo(dialogId).period != 0x7FFFFFFF, 0); } else if (position == 2 && locationType == 1 || position == 1 && locationType == 2 || position == 3 && locationType == 3) { if (getLocationController().isSharingLocation(dialogId)) { getLocationController().removeSharingLocation(dialogId); + adapter.notifyDataSetChanged(); finishFragment(); } else { - openShareLiveLocation(0); + openShareLiveLocation(false, 0); } } else { Object object = adapter.getItem(position); @@ -1205,7 +1218,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } animatorSet = new AnimatorSet(); animatorSet.setDuration(200); - animatorSet.playTogether(ObjectAnimator.ofFloat(markerImageView, View.TRANSLATION_Y, markerTop - AndroidUtilities.dp(10))); + animatorSet.playTogether(ObjectAnimator.ofFloat(markerImageView, View.TRANSLATION_Y, markerTop - dp(10))); animatorSet.start(); } else if (ev.getAction() == MotionEvent.ACTION_UP) { if (animatorSet != null) { @@ -1261,7 +1274,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter IMapsProvider.IMapStyleOptions style = ApplicationLoader.getMapsProvider().loadRawResourceStyle(ApplicationLoader.applicationContext, themeResId); this.map.setMapStyle(style); } - this.map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + this.map.setPadding(dp(70), 0, dp(70), dp(10)); onMapInit(); }); mapsInitialized = true; @@ -1282,7 +1295,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter mapViewClip.addView(frameLayout1, LayoutHelper.createFrame(62, 76, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); BackupImageView backupImageView = new BackupImageView(context); - backupImageView.setRoundRadius(AndroidUtilities.dp(26)); + backupImageView.setRoundRadius(dp(26)); backupImageView.setForUserOrChat(chat, new AvatarDrawable(chat)); frameLayout1.addView(backupImageView, LayoutHelper.createFrame(52, 52, Gravity.LEFT | Gravity.TOP, 5, 5, 0, 0)); @@ -1363,9 +1376,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter for (int a = 0; a < 2; a++) { undoView[a] = new UndoView(context); - undoView[a].setAdditionalTranslationY(AndroidUtilities.dp(10)); + undoView[a].setAdditionalTranslationY(dp(10)); if (Build.VERSION.SDK_INT >= 21) { - undoView[a].setTranslationZ(AndroidUtilities.dp(5)); + undoView[a].setTranslationZ(dp(5)); } mapViewClip.addView(undoView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); } @@ -1380,18 +1393,18 @@ public class LocationActivity extends BaseFragment implements NotificationCenter shadowDrawable.draw(canvas); if (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE) { - int w = AndroidUtilities.dp(36); - int y = padding.top + AndroidUtilities.dp(10); - rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4)); + int w = dp(36); + int y = padding.top + dp(10); + rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + dp(4)); int color = getThemedColor(Theme.key_sheet_scrollUp); int alpha = Color.alpha(color); Theme.dialogs_onlineCirclePaint.setColor(color); - canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); + canvas.drawRoundRect(rect, dp(2), dp(2), Theme.dialogs_onlineCirclePaint); } } }; if (Build.VERSION.SDK_INT >= 21) { - shadow.setTranslationZ(AndroidUtilities.dp(6)); + shadow.setTranslationZ(dp(6)); } mapViewClip.addView(shadow, layoutParams); @@ -1494,7 +1507,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } searchAreaButton.setTag(show ? 1 : null); AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_X, show ? 0 : -AndroidUtilities.dp(80))); + animatorSet.playTogether(ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_X, show ? 0 : -dp(80))); animatorSet.setDuration(180); animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); animatorSet.start(); @@ -1509,11 +1522,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(85), Bitmap.Config.ARGB_8888); + result = Bitmap.createBitmap(dp(62), dp(85), Bitmap.Config.ARGB_8888); result.eraseColor(Color.TRANSPARENT); Canvas canvas = new Canvas(result); Drawable drawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.map_pin_photo); - drawable.setBounds(0, 0, AndroidUtilities.dp(62), AndroidUtilities.dp(85)); + drawable.setBounds(0, 0, dp(62), dp(85)); drawable.draw(canvas); Paint roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -1525,13 +1538,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(50) / (float) bitmap.getWidth(); - matrix.postTranslate(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); + float scale = dp(50) / (float) bitmap.getWidth(); + matrix.postTranslate(dp(6), dp(6)); matrix.postScale(scale, scale); roundPaint.setShader(shader); shader.setLocalMatrix(matrix); - 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); + bitmapRect.set(dp(6), dp(6), dp(50 + 6), dp(50 + 6)); + canvas.drawRoundRect(bitmapRect, dp(25), dp(25), roundPaint); } } else { AvatarDrawable avatarDrawable = new AvatarDrawable(); @@ -1540,8 +1553,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else if (liveLocation.chat != null) { avatarDrawable.setInfo(currentAccount, liveLocation.chat); } - canvas.translate(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); - avatarDrawable.setBounds(0, 0, AndroidUtilities.dp(50), AndroidUtilities.dp(50)); + canvas.translate(dp(6), dp(6)); + avatarDrawable.setBounds(0, 0, dp(50), dp(50)); avatarDrawable.draw(canvas); } canvas.restore(); @@ -1619,7 +1632,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return true; }, () -> { if (map != null) { - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + map.setPadding(dp(70), 0, dp(70), dp(10)); } if (!proximitySheet.getRadiusSet()) { if (previousRadius > 0) { @@ -1636,7 +1649,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter proximitySheet.show(); } - private void openShareLiveLocation(int proximityRadius) { + private void openShareLiveLocation(boolean expand, int proximityRadius) { if (delegate == null || disablePermissionCheck() || getParentActivity() == null || myLocation == null || !checkGpsEnabled()) { return; } @@ -1649,7 +1662,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter 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), null).show(); + AlertsCreator.createBackgroundLocationPermissionDialog(activity, getMessagesController().getUser(getUserConfig().getClientUserId()), () -> openShareLiveLocation(expand, askWithRadius), null).show(); return; } } @@ -1660,7 +1673,46 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else { user = null; } - showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> shareLiveLocation(user, param, proximityRadius), null)); + showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), expand, user, param -> { + if (expand) { + LocationController.SharingLocationInfo info = getLocationController().getSharingLocationInfo(dialogId); + if (info != null) { + TLRPC.TL_messages_editMessage req = new TLRPC.TL_messages_editMessage(); + req.peer = getMessagesController().getInputPeer(info.did); + req.id = info.mid; + req.flags |= 16384; + req.media = new TLRPC.TL_inputMediaGeoLive(); + req.media.stopped = false; + req.media.geo_point = new TLRPC.TL_inputGeoPoint(); + Location lastKnownLocation = LocationController.getInstance(currentAccount).getLastKnownLocation(); + 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 = LocationController.getHeading(lastKnownLocation); + req.media.flags |= 4; + req.media.period = info.period = param == 0x7FFFFFFF ? 0x7FFFFFFF : info.period + param; + info.stopTime = param == 0x7FFFFFFF ? Integer.MAX_VALUE : info.stopTime + param; + req.media.flags |= 2; + if (info.messageObject != null && info.messageObject.messageOwner != null && info.messageObject.messageOwner.media != null) { + info.messageObject.messageOwner.media.period = info.period; +// ArrayList messages = new ArrayList<>(); +// messages.add(info.messageObject.messageOwner); + getMessagesStorage().replaceMessageIfExists(info.messageObject.messageOwner, null, null, true); + } + getConnectionsManager().sendRequest(req, null); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.liveLocationsChanged); + } + return; + } + shareLiveLocation(user, param, proximityRadius); + }, null)); } private void shareLiveLocation(TLRPC.User user, int period, int radius) { @@ -1694,11 +1746,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter try { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(0xffffffff); - Bitmap bitmap = Bitmap.createBitmap(AndroidUtilities.dp(12), AndroidUtilities.dp(12), Bitmap.Config.ARGB_8888); + Bitmap bitmap = Bitmap.createBitmap(dp(12), dp(12), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); - canvas.drawCircle(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint); + canvas.drawCircle(dp(6), dp(6), dp(6), paint); paint.setColor(LocationCell.getColorForIndex(num)); - canvas.drawCircle(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(5), paint); + canvas.drawCircle(dp(6), dp(6), dp(5), paint); canvas.setBitmap(null); return bitmapCache[num % 7] = bitmap; } catch (Throwable e) { @@ -1901,7 +1953,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (view != null) { RecyclerView.ViewHolder holder = listView.findContainingViewHolder(view); if (holder != null && holder.getAdapterPosition() == 0) { - int min = locationType == LOCATION_TYPE_SEND ? 0 : AndroidUtilities.dp(66); + int min = locationType == LOCATION_TYPE_SEND ? 0 : dp(66); int top = view.getTop(); if (top < -min) { IMapsProvider.CameraPosition cameraPosition = map.getCameraPosition(); @@ -2062,7 +2114,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } if (mapViewClip != null) { - mapViewClip.addView(mapView.getView(), 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); + mapViewClip.addView(mapView.getView(), 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + dp(10), Gravity.TOP | Gravity.LEFT)); if (overlayView != null) { try { if (overlayView.getParent() instanceof ViewGroup) { @@ -2072,7 +2124,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } catch (Exception ignore) { } - mapViewClip.addView(overlayView, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); + mapViewClip.addView(overlayView, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + dp(10), Gravity.TOP | Gravity.LEFT)); } updateClipView(false); maybeShowProximityHint(); @@ -2092,11 +2144,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter preferences.edit().putInt("proximityhint", ++val).commit(); if (DialogObject.isUserDialog(dialogId)) { TLRPC.User user = getMessagesController().getUser(dialogId); - hintView.setOverrideText(LocaleController.formatString("ProximityTooltioUser", R.string.ProximityTooltioUser, UserObject.getFirstName(user))); + hintView.setText(LocaleController.formatString("ProximityTooltioUser", R.string.ProximityTooltioUser, UserObject.getFirstName(user))); } else { - hintView.setOverrideText(LocaleController.getString("ProximityTooltioGroup", R.string.ProximityTooltioGroup)); + hintView.setText(LocaleController.getString("ProximityTooltioGroup", R.string.ProximityTooltioGroup)); } - hintView.showForView(proximityButton, true); + hintView.show(); } } @@ -2109,8 +2161,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return; } View child = listView.getChildAt(0); - int offset = AndroidUtilities.dp(258) + child.getTop(); - if (offset < 0 || offset > AndroidUtilities.dp(258)) { + int offset = dp(258) + child.getTop(); + if (offset < 0 || offset > dp(258)) { return; } listView.smoothScrollBy(0, offset); @@ -2151,31 +2203,31 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (overlayView != null) { overlayView.setTranslationY(Math.max(0, -top / 2)); } - float translationY = Math.min(overScrollHeight - mapTypeButton.getMeasuredHeight() - AndroidUtilities.dp(64 + (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE ? 30 : 10)), -top); + float translationY = Math.min(overScrollHeight - mapTypeButton.getMeasuredHeight() - 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); + hintView.setTranslationY(translationY); } if (searchAreaButton != null) { searchAreaButton.setTranslation(translationY); } if (markerImageView != null) { - markerImageView.setTranslationY(markerTop = -top - AndroidUtilities.dp(markerImageView.getTag() == null ? 48 : 69) + height / 2); + markerImageView.setTranslationY(markerTop = -top - dp(markerImageView.getTag() == null ? 48 : 69) + height / 2); } if (!fromLayout) { layoutParams = (FrameLayout.LayoutParams) mapView.getView().getLayoutParams(); - if (layoutParams != null && layoutParams.height != overScrollHeight + AndroidUtilities.dp(10)) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + if (layoutParams != null && layoutParams.height != overScrollHeight + dp(10)) { + layoutParams.height = overScrollHeight + dp(10); if (map != null) { - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + map.setPadding(dp(70), 0, dp(70), dp(10)); } mapView.getView().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); + if (layoutParams != null && layoutParams.height != overScrollHeight + dp(10)) { + layoutParams.height = overScrollHeight + dp(10); overlayView.setLayoutParams(layoutParams); } } @@ -2191,11 +2243,11 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return; } if (locationType == LOCATION_TYPE_LIVE_VIEW) { - overScrollHeight = viewHeight - AndroidUtilities.dp(66) - height; + overScrollHeight = viewHeight - dp(66) - height; } else if (locationType == 2) { - overScrollHeight = viewHeight - AndroidUtilities.dp(66 + 7) - height; + overScrollHeight = viewHeight - dp(66 + 7) - height; } else { - overScrollHeight = viewHeight - AndroidUtilities.dp(66) - height; + overScrollHeight = viewHeight - dp(66) - height; } FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); @@ -2214,16 +2266,16 @@ public class LocationActivity extends BaseFragment implements NotificationCenter adapter.setOverScrollHeight(overScrollHeight); layoutParams = (FrameLayout.LayoutParams) mapView.getView().getLayoutParams(); if (layoutParams != null) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + layoutParams.height = overScrollHeight + dp(10); if (map != null) { - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + map.setPadding(dp(70), 0, dp(70), dp(10)); } mapView.getView().setLayoutParams(layoutParams); } if (overlayView != null) { layoutParams = (FrameLayout.LayoutParams) overlayView.getLayoutParams(); if (layoutParams != null) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + layoutParams.height = overScrollHeight + dp(10); overlayView.setLayoutParams(layoutParams); } } @@ -2238,10 +2290,10 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else { top = 0; } - layoutManager.scrollToPositionWithOffset(0, -AndroidUtilities.dp(top)); + layoutManager.scrollToPositionWithOffset(0, -dp(top)); updateClipView(false); listView.post(() -> { - layoutManager.scrollToPositionWithOffset(0, -AndroidUtilities.dp(top)); + layoutManager.scrollToPositionWithOffset(0, -dp(top)); updateClipView(false); }); } else { @@ -2379,7 +2431,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } if (builder != null) { if (firstFocus) { - listView.smoothScrollBy(0, AndroidUtilities.dp(66 * 1.5f)); + listView.smoothScrollBy(0, dp(66 * 1.5f)); } firstFocus = false; adapter.setLiveLocations(markers); @@ -2394,7 +2446,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter bounds = builder.build(); if (messages.size() > 1) { try { - moveToBounds = ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, AndroidUtilities.dp(80 + 33)); + moveToBounds = ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, dp(80 + 33)); map.moveCamera(moveToBounds); moveToBounds = null; } catch (Exception e) { @@ -2422,8 +2474,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter builder.include(northEast); bounds = builder.build(); try { - int height = (int) (proximitySheet.getCustomView().getMeasuredHeight() - AndroidUtilities.dp(40) + mapViewClip.getTranslationY()); - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), height); + int height = (int) (proximitySheet.getCustomView().getMeasuredHeight() - dp(40) + mapViewClip.getTranslationY()); + map.setPadding(dp(70), 0, dp(70), height); if (animated) { map.animateCamera(ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, 0), 500, null); } else { @@ -2453,8 +2505,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter builder.include(northEast); bounds = builder.build(); try { - int height = proximitySheet.getCustomView().getMeasuredHeight() - AndroidUtilities.dp(100); - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), height); + int height = proximitySheet.getCustomView().getMeasuredHeight() - dp(100); + map.setPadding(dp(70), 0, dp(70), height); map.moveCamera(ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, 0)); } catch (Exception e) { FileLog.e(e); @@ -2560,6 +2612,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } } else if (id == NotificationCenter.liveLocationsChanged) { if (adapter != null) { + adapter.notifyDataSetChanged(); adapter.updateLiveLocationCell(); } } else if (id == NotificationCenter.didReceiveNewMessages) { @@ -2779,7 +2832,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter @Override public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 30) { - openShareLiveLocation(askWithRadius); + openShareLiveLocation(false, askWithRadius); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 8c8316391..b9c4841b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -8,6 +8,11 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.replaceArrows; +import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -18,6 +23,7 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; +import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -44,6 +50,7 @@ import android.os.Looper; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.Editable; +import android.text.InputFilter; import android.text.InputType; import android.text.Layout; import android.text.Spannable; @@ -153,6 +160,7 @@ import org.telegram.ui.Components.ProxyDrawable; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.SimpleThemeDescription; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.SlideView; @@ -191,7 +199,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AUTH_TYPE_FLASH_CALL = 3, AUTH_TYPE_CALL = 4, AUTH_TYPE_MISSED_CALL = 11, - AUTH_TYPE_FRAGMENT_SMS = 15; + AUTH_TYPE_FRAGMENT_SMS = 15, + AUTH_TYPE_WORD = 16, + AUTH_TYPE_PHRASE = 17; private final static int MODE_LOGIN = 0, MODE_CANCEL_ACCOUNT_DELETION = 1, @@ -214,7 +224,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No VIEW_ADD_EMAIL = 12, VIEW_CODE_EMAIL_SETUP = 13, VIEW_CODE_EMAIL = 14, - VIEW_CODE_FRAGMENT_SMS = 15; + VIEW_CODE_FRAGMENT_SMS = 15, + VIEW_CODE_WORD = 16, + VIEW_CODE_PHRASE = 17; public final static int COUNTRY_STATE_NOT_SET_OR_VALID = 0, COUNTRY_STATE_EMPTY = 1, @@ -227,7 +239,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AUTH_TYPE_FLASH_CALL, AUTH_TYPE_CALL, AUTH_TYPE_MISSED_CALL, - AUTH_TYPE_FRAGMENT_SMS + AUTH_TYPE_FRAGMENT_SMS, + AUTH_TYPE_PHRASE, + AUTH_TYPE_WORD }) public @interface AuthType {} @@ -258,7 +272,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No VIEW_ADD_EMAIL, VIEW_CODE_EMAIL_SETUP, VIEW_CODE_EMAIL, - VIEW_CODE_FRAGMENT_SMS + VIEW_CODE_FRAGMENT_SMS, + VIEW_CODE_WORD, + VIEW_CODE_PHRASE }) private @interface ViewNumber {} @@ -271,7 +287,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @ViewNumber private int currentViewNum; - private SlideView[] views = new SlideView[16]; + private SlideView[] views = new SlideView[18]; private CustomPhoneKeyboardView keyboardView; private ValueAnimator keyboardAnimator; @@ -483,8 +499,15 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return super.onFragmentCreate(); } + private View cachedFragmentView; @Override public View createView(Context context) { + if (cachedFragmentView != null) { + fragmentView = cachedFragmentView; + cachedFragmentView = null; + return fragmentView; + } + actionBar.setAddToContainer(false); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -618,6 +641,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No views[VIEW_CODE_EMAIL_SETUP] = new LoginActivityEmailCodeView(context, true); views[VIEW_CODE_EMAIL] = new LoginActivityEmailCodeView(context, false); views[VIEW_CODE_FRAGMENT_SMS] = new LoginActivitySmsView(context, AUTH_TYPE_FRAGMENT_SMS); + views[VIEW_CODE_WORD] = new LoginActivityPhraseView(context, AUTH_TYPE_WORD); + views[VIEW_CODE_PHRASE] = new LoginActivityPhraseView(context, AUTH_TYPE_PHRASE); for (int a = 0; a < views.length; a++) { views[a].setVisibility(a == 0 ? View.VISIBLE : View.GONE); @@ -669,6 +694,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } floatingAutoAnimator = VerticalPositionAutoAnimator.attach(floatingButtonContainer); sizeNotifierFrameLayout.addView(floatingButtonContainer, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 24, 16)); +// ScaleStateListAnimator.apply(floatingButtonContainer, .1f, 1.4f); floatingButtonContainer.setOnClickListener(view -> onDoneButtonPressed()); floatingAutoAnimator.addUpdateListener((animation, value, velocity) -> { if (phoneNumberConfirmView != null) { @@ -683,7 +709,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No finishFragment(); } }); - backButtonView.setContentDescription(LocaleController.getString(R.string.Back)); + backButtonView.setContentDescription(getString(R.string.Back)); int padding = AndroidUtilities.dp(4); backButtonView.setPadding(padding, padding, padding, padding); sizeNotifierFrameLayout.addView(backButtonView, LayoutHelper.createFrame(32, 32, Gravity.LEFT | Gravity.TOP, 16, 16, 0, 0)); @@ -707,7 +733,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No floatingButtonIcon.setTransformType(TransformableLoginButtonView.TRANSFORM_OPEN_ARROW); floatingButtonIcon.setProgress(1f); floatingButtonIcon.setDrawBackground(false); - floatingButtonContainer.setContentDescription(LocaleController.getString("Done", R.string.Done)); + floatingButtonContainer.setContentDescription(getString("Done", R.string.Done)); floatingButtonContainer.addView(floatingButtonIcon, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60)); floatingProgressView = new RadialProgressView(context); @@ -877,6 +903,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AndroidUtilities.hideKeyboard(fragmentView); AndroidUtilities.requestAltFocusable(getParentActivity(), classGuid); } + + if (currentViewNum >= 0 && currentViewNum < views.length) { + views[currentViewNum].onResume(); + } } @Override @@ -1064,7 +1094,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(title); builder.setMessage(text); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setPositiveButton(getString("OK", R.string.OK), null); showDialog(builder.create()); } @@ -1128,8 +1158,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity()); if (banned) { - builder.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder.setMessage(LocaleController.getString("BannedPhoneNumber", R.string.BannedPhoneNumber)); + builder.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder.setMessage(getString("BannedPhoneNumber", R.string.BannedPhoneNumber)); } else { if (inputData != null && inputData.patterns != null && !inputData.patterns.isEmpty() && inputData.country != null) { int patternLength = Integer.MAX_VALUE; @@ -1140,18 +1170,18 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } if (PhoneFormat.stripExceptNumbers(phoneNumber).length() - inputData.country.code.length() < patternLength) { - builder.setTitle(LocaleController.getString(R.string.WrongNumberFormat)); + builder.setTitle(getString(R.string.WrongNumberFormat)); builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("ShortNumberInfo", R.string.ShortNumberInfo, inputData.country.name, inputData.phoneNumber))); } else { - builder.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder.setMessage(LocaleController.getString(R.string.InvalidPhoneNumber)); + builder.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder.setMessage(getString(R.string.InvalidPhoneNumber)); } } else { - builder.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder.setMessage(LocaleController.getString(R.string.InvalidPhoneNumber)); + builder.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder.setMessage(getString(R.string.InvalidPhoneNumber)); } } - builder.setNeutralButton(LocaleController.getString("BotHelp", R.string.BotHelp), (dialog, which) -> { + builder.setNeutralButton(getString("BotHelp", R.string.BotHelp), (dialog, which) -> { try { PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); String version = String.format(Locale.US, "%s (%d)", pInfo.versionName, pInfo.versionCode); @@ -1169,13 +1199,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No fragment.getParentActivity().startActivity(Intent.createChooser(mailer, "Send email...")); } catch (Exception e) { AlertDialog.Builder builder2 = new AlertDialog.Builder(fragment.getParentActivity()); - builder2.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder2.setMessage(LocaleController.getString("NoMailInstalled", R.string.NoMailInstalled)); - builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder2.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder2.setMessage(getString("NoMailInstalled", R.string.NoMailInstalled)); + builder2.setPositiveButton(getString("OK", R.string.OK), null); fragment.showDialog(builder2.create()); } }); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setPositiveButton(getString("OK", R.string.OK), null); fragment.showDialog(builder.create()); } @@ -1291,10 +1321,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("StopLoadingTitle", R.string.StopLoadingTitle)); - builder.setMessage(LocaleController.getString("StopLoading", R.string.StopLoading)); - builder.setPositiveButton(LocaleController.getString("WaitMore", R.string.WaitMore), null); - builder.setNegativeButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { + builder.setTitle(getString("StopLoadingTitle", R.string.StopLoadingTitle)); + builder.setMessage(getString("StopLoading", R.string.StopLoading)); + builder.setPositiveButton(getString("WaitMore", R.string.WaitMore), null); + builder.setNegativeButton(getString("Stop", R.string.Stop), (dialogInterface, i) -> { views[currentViewNum].onCancelPressed(); needHideProgress(true); }); @@ -1488,7 +1518,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No public void setPage(@ViewNumber int page, boolean animated, Bundle params, boolean back) { boolean needFloatingButton = page == VIEW_PHONE_INPUT || page == VIEW_REGISTER || page == VIEW_PASSWORD || - page == VIEW_NEW_PASSWORD_STAGE_1 || page == VIEW_NEW_PASSWORD_STAGE_2 || page == VIEW_ADD_EMAIL; + page == VIEW_NEW_PASSWORD_STAGE_1 || page == VIEW_NEW_PASSWORD_STAGE_2 || page == VIEW_ADD_EMAIL || page == VIEW_CODE_PHRASE || page == VIEW_CODE_WORD; if (page == currentViewNum) { animated = false; } @@ -1591,11 +1621,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (getParentActivity() instanceof LaunchActivity) { if (newAccount) { newAccount = false; + pendingSwitchingAccount = true; ((LaunchActivity) getParentActivity()).switchToAccount(currentAccount, false, obj -> { Bundle args = new Bundle(); args.putBoolean("afterSignup", afterSignup); return new DialogsActivity(args); }); + pendingSwitchingAccount = false; finishFragment(); } else { @@ -1620,10 +1652,18 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } + private void fakeSuccess() { + TLRPC.TL_auth_authorization res = new TLRPC.TL_auth_authorization(); + res.user = UserConfig.getInstance(0).getCurrentUser(); + onAuthSuccess(res); + } + private void onAuthSuccess(TLRPC.TL_auth_authorization res) { onAuthSuccess(res, false); } + private boolean pendingSwitchingAccount; + private void onAuthSuccess(TLRPC.TL_auth_authorization res, boolean afterSignup) { MessagesController.getInstance(currentAccount).cleanup(); ConnectionsManager.getInstance(currentAccount).setUserId(res.user.id); @@ -1685,9 +1725,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } new AlertDialog.Builder(getContext()) - .setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)) - .setMessage(LocaleController.getString(R.string.SafetyNetErrorOccurred)) - .setPositiveButton(LocaleController.getString(R.string.OK), (dialog, which) -> { + .setTitle(getString(R.string.RestorePasswordNoEmailTitle)) + .setMessage(getString(R.string.SafetyNetErrorOccurred)) + .setPositiveButton(getString(R.string.OK), (dialog, which) -> { forceDisableSafetyNet = true; if (currentViewNum != VIEW_PHONE_INPUT) { setPage(VIEW_PHONE_INPUT, true, null, true); @@ -1783,7 +1823,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No setPage(VIEW_CODE_MESSAGE, animate, params, false); } else { if (res.timeout == 0) { - res.timeout = 60; + res.timeout = BuildVars.DEBUG_PRIVATE_VERSION ? 5 : 60; } params.putInt("timeout", res.timeout * 1000); if (res.type instanceof TLRPC.TL_auth_sentCodeTypeCall) { @@ -1820,6 +1860,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No params.putInt("resetAvailablePeriod", res.type.reset_available_period); params.putInt("resetPendingDate", res.type.reset_pending_date); setPage(VIEW_CODE_EMAIL, animate, params, false); + } else if (res.type instanceof TLRPC.TL_auth_sentCodeTypeSmsWord) { + if (res.type.beginning != null) { + params.putString("beginning", res.type.beginning); + } + setPage(VIEW_CODE_WORD, animate, params, false); + } else if (res.type instanceof TLRPC.TL_auth_sentCodeTypeSmsPhrase) { + if (res.type.beginning != null) { + params.putString("beginning", res.type.beginning); + } + setPage(VIEW_CODE_PHRASE, animate, params, false); } } } @@ -1863,14 +1913,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneNewNumber : R.string.YourNumber)); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setText(getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneNewNumber : R.string.YourNumber)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 0, 32, 0)); subtitleView = new TextView(context); - subtitleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneHelp : R.string.StartText)); + subtitleView.setText(getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneHelp : R.string.StartText)); subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitleView.setGravity(Gravity.CENTER); subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -1904,11 +1954,11 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No countryButtonLinearLayout.addView(chevronRight, LayoutHelper.createLinearRelatively(24, 24, 0, 0, 0, 14, 0)); countryOutlineView = new OutlineTextContainerView(context); - countryOutlineView.setText(LocaleController.getString(R.string.Country)); + countryOutlineView.setText(getString(R.string.Country)); countryOutlineView.addView(countryButtonLinearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 0, 0)); countryOutlineView.setForceUseCenter(true); countryOutlineView.setFocusable(true); - countryOutlineView.setContentDescription(LocaleController.getString(R.string.Country)); + countryOutlineView.setContentDescription(getString(R.string.Country)); countryOutlineView.setOnFocusChangeListener((v, hasFocus) -> countryOutlineView.animateSelection(hasFocus ? 1 : 0)); addView(countryOutlineView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 58, 16, 24, 16, 14)); countryOutlineView.setOnClickListener(view -> { @@ -1927,7 +1977,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No phoneOutlineView = new OutlineTextContainerView(context); phoneOutlineView.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 8, 16, 8)); - phoneOutlineView.setText(LocaleController.getString(R.string.PhoneNumber)); + phoneOutlineView.setText(getString(R.string.PhoneNumber)); addView(phoneOutlineView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 58, 16, 8, 16, 8)); plusTextView = new TextView(context); @@ -1960,7 +2010,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { codeField.setShowSoftInputOnFocus(!(hasCustomKeyboard() && !isCustomKeyboardForceDisabled())); } - codeField.setContentDescription(LocaleController.getString(R.string.LoginAccessibilityCountryCode)); + codeField.setContentDescription(getString(R.string.LoginAccessibilityCountryCode)); linearLayout.addView(codeField, LayoutHelper.createLinear(55, 36, -9, 0, 0, 0)); codeField.addTextChangedListener(new TextWatcher() { @Override @@ -2133,7 +2183,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No keyboardView.setDispatchBackWhenEmpty(true); if (countryState == COUNTRY_STATE_INVALID) { - setCountryButtonText(LocaleController.getString(R.string.WrongCountry)); + setCountryButtonText(getString(R.string.WrongCountry)); } } else { if (countryState == COUNTRY_STATE_INVALID) { @@ -2155,7 +2205,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { phoneField.setShowSoftInputOnFocus(!(hasCustomKeyboard() && !isCustomKeyboardForceDisabled())); } - phoneField.setContentDescription(LocaleController.getString(R.string.PhoneNumber)); + phoneField.setContentDescription(getString(R.string.PhoneNumber)); linearLayout.addView(phoneField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36)); phoneField.addTextChangedListener(new TextWatcher() { @@ -2283,7 +2333,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No int bottomMargin = 72; if (newAccount && activityMode == MODE_LOGIN) { syncContactsBox = new CheckBoxCell(context, 2); - syncContactsBox.setText(LocaleController.getString("SyncContacts", R.string.SyncContacts), "", syncContacts, false); + syncContactsBox.setText(getString("SyncContacts", R.string.SyncContacts), "", syncContacts, false); addView(syncContactsBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); bottomMargin -= 24; syncContactsBox.setOnClickListener(v -> { @@ -2294,16 +2344,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No syncContacts = !syncContacts; cell.setChecked(syncContacts, true); if (syncContacts) { - BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_on, LocaleController.getString("SyncContactsOn", R.string.SyncContactsOn)).show(); + BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_on, getString("SyncContactsOn", R.string.SyncContactsOn)).show(); } else { - BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_off, LocaleController.getString("SyncContactsOff", R.string.SyncContactsOff)).show(); + BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_off, getString("SyncContactsOff", R.string.SyncContactsOff)).show(); } }); } - if (BuildVars.DEBUG_VERSION && activityMode == MODE_LOGIN) { + if (BuildVars.DEBUG_PRIVATE_VERSION && activityMode == MODE_LOGIN) { testBackendCheckBox = new CheckBoxCell(context, 2); - testBackendCheckBox.setText(LocaleController.getString(R.string.DebugTestBackend), "", testBackend, false); + testBackendCheckBox.setText(getString(R.string.DebugTestBackend), "", testBackend, false); addView(testBackendCheckBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); bottomMargin -= 24; testBackendCheckBox.setOnClickListener(v -> { @@ -2750,16 +2800,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No preferences.edit().putBoolean("firstlogin", false).commit(); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); int resId; if (!allowCall && (!allowCancelCall || !allowReadCallLog)) { - builder.setMessage(LocaleController.getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); + builder.setMessage(getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); resId = R.raw.calls_log; } else if (!allowCancelCall || !allowReadCallLog) { - builder.setMessage(LocaleController.getString("AllowReadCallLog", R.string.AllowReadCallLog)); + builder.setMessage(getString("AllowReadCallLog", R.string.AllowReadCallLog)); resId = R.raw.calls_log; } else { - builder.setMessage(LocaleController.getString("AllowReadCall", R.string.AllowReadCall)); + builder.setMessage(getString("AllowReadCall", R.string.AllowReadCall)); resId = R.raw.incoming_calls; } builder.setTopAnimation(resId, 46, false, Theme.getColor(Theme.key_dialogTopBackground)); @@ -2827,16 +2877,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No preferences.edit().putBoolean("firstlogin", false).commit(); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); int resId; if (!allowCall && (!allowCancelCall || !allowReadCallLog)) { - builder.setMessage(LocaleController.getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); + builder.setMessage(getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); resId = R.raw.calls_log; } else if (!allowCancelCall || !allowReadCallLog) { - builder.setMessage(LocaleController.getString("AllowReadCallLog", R.string.AllowReadCallLog)); + builder.setMessage(getString("AllowReadCallLog", R.string.AllowReadCallLog)); resId = R.raw.calls_log; } else { - builder.setMessage(LocaleController.getString("AllowReadCall", R.string.AllowReadCall)); + builder.setMessage(getString("AllowReadCall", R.string.AllowReadCall)); resId = R.raw.incoming_calls; } builder.setTopAnimation(resId, 46, false, Theme.getColor(Theme.key_dialogTopBackground)); @@ -2855,11 +2905,11 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } if (countryState == COUNTRY_STATE_EMPTY) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ChooseCountry", R.string.ChooseCountry)); needHideProgress(false); return; } else if (countryState == COUNTRY_STATE_INVALID && !BuildVars.DEBUG_VERSION) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("WrongCountry", R.string.WrongCountry)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("WrongCountry", R.string.WrongCountry)); needHideProgress(false); return; } @@ -2875,15 +2925,15 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (PhoneNumberUtils.compare(phone, userPhone) && ConnectionsManager.getInstance(a).isTestBackend() == testBackend) { final int num = a; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString(R.string.AppName)); - builder.setMessage(LocaleController.getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn)); - builder.setPositiveButton(LocaleController.getString("AccountSwitch", R.string.AccountSwitch), (dialog, which) -> { + builder.setTitle(getString(R.string.AppName)); + builder.setMessage(getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn)); + builder.setPositiveButton(getString("AccountSwitch", R.string.AccountSwitch), (dialog, which) -> { if (UserConfig.selectedAccount != num) { ((LaunchActivity) getParentActivity()).switchToAccount(num, false); } finishFragment(); }); - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); + builder.setNegativeButton(getString("OK", R.string.OK), null); showDialog(builder.create()); needHideProgress(false); return; @@ -2945,11 +2995,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No try { String number = tm.getLine1Number(); if (!TextUtils.isEmpty(number)) { + settings.unknown_number = false; settings.current_number = PhoneNumberUtils.compare(phone, number); - if (!settings.current_number) { - settings.allow_flashcall = false; - } } else { + settings.unknown_number = true; if (UserConfig.getActivatedAccountsCount() > 0) { settings.allow_flashcall = false; } else { @@ -2957,7 +3006,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } } catch (Exception e) { - settings.allow_flashcall = false; + settings.unknown_number = true; FileLog.e(e); } } @@ -3020,7 +3069,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (error1 == null) { TLRPC.account_Password password = (TLRPC.account_Password) response1; if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); return; } Bundle bundle = new Bundle(); @@ -3030,25 +3079,25 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No bundle.putString("phoneFormated", phone); setPage(VIEW_PASSWORD, true, bundle, false); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else if (error.text.contains("PHONE_NUMBER_INVALID")) { needShowInvalidAlert(LoginActivity.this, phone, phoneInputData, false); } else if (error.text.contains("PHONE_PASSWORD_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.text.contains("PHONE_NUMBER_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); } else if (error.text.contains("PHONE_NUMBER_BANNED")) { needShowInvalidAlert(LoginActivity.this, phone, phoneInputData, true); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.code != -1000) { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req, phoneInputData.phoneNumber); } @@ -3093,8 +3142,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTopAnimation(R.raw.incoming_calls, 46, false, Theme.getColor(Theme.key_dialogTopBackground)); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); - builder.setMessage(LocaleController.getString("AllowFillNumber", R.string.AllowFillNumber)); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); + builder.setMessage(getString("AllowFillNumber", R.string.AllowFillNumber)); permissionsShowDialog = showDialog(builder.create(), true, null); needRequestPermissions = true; } else { @@ -3211,7 +3260,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("YourPhone", R.string.YourPhone); + return getString("YourPhone", R.string.YourPhone); } @Override @@ -3254,6 +3303,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private String requestPhone; private String emailPhone; private CodeFieldContainer codeFieldContainer; + private TextView prevTypeTextView; private TextView confirmTextView; private TextView titleTextView; private ImageView blackImageView; @@ -3299,6 +3349,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private int currentType; @AuthType private int nextType; + @AuthType + private int prevType; private boolean isResendingCode = false; @@ -3308,6 +3360,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private int length; private String url; + private Bundle nextCodeParams; + private TLRPC.TL_auth_sentCode nextCodeAuth; + private boolean postedErrorColorTimeout; private Runnable errorColorTimeout = () -> { postedErrorColorTimeout = false; @@ -3333,7 +3388,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleTextView = new TextView(context); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); @@ -3345,12 +3400,12 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No overrideTitle = null; break; case MODE_CANCEL_ACCOUNT_DELETION: - overrideTitle = LocaleController.getString(R.string.CancelAccountReset); + overrideTitle = getString(R.string.CancelAccountReset); break; } FrameLayout centerContainer = null; if (currentType == AUTH_TYPE_MISSED_CALL) { - titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString("MissedCallDescriptionTitle", R.string.MissedCallDescriptionTitle)); + titleTextView.setText(overrideTitle != null ? overrideTitle : getString("MissedCallDescriptionTitle", R.string.MissedCallDescriptionTitle)); FrameLayout frameLayout = new FrameLayout(context); missedCallArrowIcon = new ImageView(context); @@ -3368,7 +3423,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No missedCallDescriptionSubtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); missedCallDescriptionSubtitle.setGravity(Gravity.CENTER_HORIZONTAL); missedCallDescriptionSubtitle.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - missedCallDescriptionSubtitle.setText(AndroidUtilities.replaceTags(LocaleController.getString("MissedCallDescriptionSubtitle", R.string.MissedCallDescriptionSubtitle))); + missedCallDescriptionSubtitle.setText(AndroidUtilities.replaceTags(getString("MissedCallDescriptionSubtitle", R.string.MissedCallDescriptionSubtitle))); addView(missedCallDescriptionSubtitle, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 36, 16, 36, 0)); @@ -3384,7 +3439,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No prefixTextView = new TextView(context); prefixTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); prefixTextView.setMaxLines(1); - prefixTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + prefixTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); prefixTextView.setPadding(0, 0, 0, 0); prefixTextView.setGravity(Gravity.CENTER_VERTICAL); @@ -3397,7 +3452,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No missedCallDescriptionSubtitle2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); missedCallDescriptionSubtitle2.setGravity(Gravity.CENTER_HORIZONTAL); missedCallDescriptionSubtitle2.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - missedCallDescriptionSubtitle2.setText(AndroidUtilities.replaceTags(LocaleController.getString("MissedCallDescriptionSubtitle2", R.string.MissedCallDescriptionSubtitle2))); + missedCallDescriptionSubtitle2.setText(AndroidUtilities.replaceTags(getString("MissedCallDescriptionSubtitle2", R.string.MissedCallDescriptionSubtitle2))); addView(missedCallDescriptionSubtitle2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 36, 28, 36, 12)); } else if (currentType == AUTH_TYPE_FLASH_CALL) { @@ -3420,7 +3475,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No blueImageView.setAnimation(hintDrawable); frameLayout.addView(blueImageView, LayoutHelper.createFrame(64, 64)); - titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString(R.string.YourCode)); + titleTextView.setText(overrideTitle != null ? overrideTitle : getString(R.string.YourCode)); innerLinearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 0)); innerLinearLayout.addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 8, 0, 0)); } else { @@ -3445,7 +3500,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No blueImageView.setTranslationY(-AndroidUtilities.dp(24)); } frameLayout.addView(blueImageView, LayoutHelper.createFrame(size, size, Gravity.LEFT | Gravity.TOP, 0, 0, 0, currentType == AUTH_TYPE_MESSAGE && !AndroidUtilities.isSmallScreen() ? -AndroidUtilities.dp(16) : 0)); - titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString(currentType == AUTH_TYPE_MESSAGE ? R.string.SentAppCodeTitle : R.string.SentSmsCodeTitle)); + titleTextView.setText(overrideTitle != null ? overrideTitle : getString(currentType == AUTH_TYPE_MESSAGE ? R.string.SentAppCodeTitle : R.string.SentSmsCodeTitle)); addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 18, 0, 0)); int sideMargin = currentType == AUTH_TYPE_FRAGMENT_SMS ? 16 : 0; addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, sideMargin, 17, sideMargin, 0)); @@ -3464,19 +3519,34 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No codeFieldContainer.setVisibility(GONE); } + prevTypeTextView = new LoadingTextView(context); + prevTypeTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + prevTypeTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + prevTypeTextView.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); + prevTypeTextView.setOnClickListener(v -> onBackPressed(true)); + addView(prevTypeTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 18, 0, 0)); + prevTypeTextView.setVisibility(View.GONE); + problemFrame = new FrameLayout(context); timeText = new LoadingTextView(context) { + @Override + protected boolean isResendingCode() { + return isResendingCode; + } @Override protected boolean isRippleEnabled() { return getVisibility() == View.VISIBLE && !(time > 0 && timeTimer != null); } }; + timeText.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); timeText.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - timeText.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - timeText.setOnClickListener(v-> { + timeText.setGravity(Gravity.TOP | Gravity.LEFT); + timeText.setOnClickListener(v -> { // if (isRequestingFirebaseSms || isResendingCode) { // return; // } @@ -3487,17 +3557,18 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No timeText.invalidate(); timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); - if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { // timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { - timeText.setText(LocaleController.getString("Calling", R.string.Calling)); + timeText.setText(getString(R.string.Calling)); } else { - timeText.setText(LocaleController.getString("SendingSms", R.string.SendingSms)); + timeText.setText(getString(R.string.SendingSms)); } Bundle params = new Bundle(); params.putString("phone", phone); params.putString("ephone", emailPhone); params.putString("phoneFormated", requestPhone); + params.putInt("prevType", currentType); createCodeTimer(); TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); @@ -3505,7 +3576,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No req.phone_code_hash = phoneHash; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { - AndroidUtilities.runOnUIThread(() -> fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response)); + AndroidUtilities.runOnUIThread(() -> { + nextCodeParams = params; + nextCodeAuth = (TLRPC.TL_auth_sentCode) response; + if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsPhrase) { + nextType = AUTH_TYPE_PHRASE; + } else if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsWord) { + nextType = AUTH_TYPE_WORD; + } + fillNextCodeParams(nextCodeParams, nextCodeAuth); + }); } else if (error != null && error.text != null) { AndroidUtilities.runOnUIThread(() -> lastError = error.text); } @@ -3537,6 +3617,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No errorViewSwitcher.setOutAnimation(anim); problemText = new LoadingTextView(context) { + @Override + protected boolean isResendingCode() { + return isResendingCode; + } @Override protected boolean isRippleEnabled() { return isClickable() && getVisibility() == View.VISIBLE && !(nextPressed || timeText != null && timeText.getVisibility() != View.GONE || isResendingCode); @@ -3576,7 +3660,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No openFragmentButton.addView(openFragmentImageView, LayoutHelper.createLinear(36, 36, Gravity.CENTER_VERTICAL, 0, 0, 2, 0)); openFragmentButtonText = new TextView(context); - openFragmentButtonText.setText(LocaleController.getString(R.string.OpenFragment)); + openFragmentButtonText.setText(getString(R.string.OpenFragment)); openFragmentButtonText.setTextColor(Color.WHITE); openFragmentButtonText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); openFragmentButtonText.setGravity(Gravity.CENTER); @@ -3585,7 +3669,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } wrongCode = new TextView(context); - wrongCode.setText(LocaleController.getString("WrongCode", R.string.WrongCode)); + wrongCode.setText(getString(R.string.WrongCode)); wrongCode.setLineSpacing(AndroidUtilities.dp(2), 1.0f); wrongCode.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); wrongCode.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); @@ -3603,6 +3687,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType != AUTH_TYPE_FRAGMENT_SMS) { problemText.setOnClickListener(v -> { + if (nextCodeParams != null && nextCodeAuth != null) { + fillNextCodeParams(nextCodeParams, nextCodeAuth); + return; + } if (nextPressed || timeText != null && timeText.getVisibility() != View.GONE || isResendingCode) { return; } @@ -3613,10 +3701,29 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } resendCode(); } else { + TLRPC.TL_auth_reportMissingCode req = new TLRPC.TL_auth_reportMissingCode(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + req.mnc = ""; + String networkOperator = null; + try { + TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); + networkOperator = tm.getNetworkOperator(); + if (!TextUtils.isEmpty(networkOperator)) { + final String mcc = networkOperator.substring(0, 3); + final String mnc = networkOperator.substring(3); +// req.mcc = mcc; + req.mnc = mnc; + } + } catch (Exception e) { + FileLog.e(e); + } + String finalNetworkOperator = networkOperator; + getConnectionsManager().sendRequest(req, null, ConnectionsManager.RequestFlagWithoutLogin); new AlertDialog.Builder(context) - .setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)) + .setTitle(getString(R.string.RestorePasswordNoEmailTitle)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("DidNotGetTheCodeInfo", R.string.DidNotGetTheCodeInfo, phone))) - .setNeutralButton(LocaleController.getString(R.string.DidNotGetTheCodeHelpButton), (dialog, which) -> { + .setNeutralButton(getString(R.string.DidNotGetTheCodeHelpButton), (dialog, which) -> { try { PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); String version = String.format(Locale.US, "%s (%d)", pInfo.versionName, pInfo.versionCode); @@ -3625,14 +3732,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No mailer.setData(Uri.parse("mailto:")); mailer.putExtra(Intent.EXTRA_EMAIL, new String[]{"sms@telegram.org"}); mailer.putExtra(Intent.EXTRA_SUBJECT, "Android registration/login issue " + version + " " + emailPhone); - mailer.putExtra(Intent.EXTRA_TEXT, "Phone: " + requestPhone + "\nApp version: " + version + "\nOS version: SDK " + Build.VERSION.SDK_INT + "\nDevice Name: " + Build.MANUFACTURER + Build.MODEL + "\nLocale: " + Locale.getDefault() + "\nError: " + lastError); + mailer.putExtra(Intent.EXTRA_TEXT, "Phone: " + requestPhone + "\nApp version: " + version + "\nOS version: SDK " + Build.VERSION.SDK_INT + "\nDevice Name: " + Build.MANUFACTURER + Build.MODEL + (finalNetworkOperator != null ? "\nOperator: " + finalNetworkOperator : "") + "\nLocale: " + Locale.getDefault() + "\nError: " + lastError); getContext().startActivity(Intent.createChooser(mailer, "Send email...")); } catch (Exception e) { - needShowAlert(LocaleController.getString(R.string.AppName), LocaleController.getString("NoMailInstalled", R.string.NoMailInstalled)); + needShowAlert(getString(R.string.AppName), getString("NoMailInstalled", R.string.NoMailInstalled)); } }) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setNegativeButton(LocaleController.getString(R.string.DidNotGetTheCodeEditNumberButton), (dialog, which) -> setPage(VIEW_PHONE_INPUT, true, null, true)) + .setPositiveButton(getString(R.string.Close), null) + .setNegativeButton(getString(R.string.DidNotGetTheCodeEditNumberButton), (dialog, which) -> setPage(VIEW_PHONE_INPUT, true, null, true)) .show(); } }); @@ -3705,6 +3812,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No params.putString("phone", phone); params.putString("ephone", emailPhone); params.putString("phoneFormated", requestPhone); + params.putInt("prevType", currentType); nextPressed = true; @@ -3714,21 +3822,28 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { nextPressed = false; if (error == null) { - fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); + nextCodeParams = params; + nextCodeAuth = (TLRPC.TL_auth_sentCode) response; + if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsPhrase) { + nextType = AUTH_TYPE_PHRASE; + } else if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsWord) { + nextType = AUTH_TYPE_WORD; + } + fillNextCodeParams(nextCodeParams, nextCodeAuth); } else { if (error.text != null) { if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.FloodWait)); } else if (error.code != -1000) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.ErrorOccurred) + "\n" + error.text); } } } @@ -3814,7 +3929,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType == AUTH_TYPE_FLASH_CALL || currentType == AUTH_TYPE_MISSED_CALL) { return phone; } else { - return LocaleController.getString("YourCode", R.string.YourCode); + return getString("YourCode", R.string.YourCode); } } @@ -3826,6 +3941,23 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public void setParams(Bundle params, boolean restore) { if (params == null) { + if (nextCodeParams != null && nextCodeAuth != null) { + setProblemTextVisible(true); + timeText.setVisibility(GONE); + if (problemText != null) { + problemText.setVisibility(VISIBLE); + problemText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + int resId; + if (nextType == AUTH_TYPE_PHRASE) { + resId = R.string.ReturnEnteringPhrase; + } else if (nextType == AUTH_TYPE_WORD) { + resId = R.string.ReturnEnteringWord; + } else { + resId = R.string.ReturnEnteringSMS; + } + problemText.setText(AndroidUtilities.replaceArrows(getString(resId), true, dp(1), dp(1))); + } + } return; } waitingForEvent = true; @@ -3855,11 +3987,15 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No pattern = params.getString("pattern"); prefix = params.getString("prefix"); length = params.getInt("length"); + prevType = params.getInt("prevType", 0); if (length == 0) { length = 5; } url = params.getString("url"); + nextCodeParams = null; + nextCodeAuth = null; + codeFieldContainer.setNumbersCount(length, currentType); for (CodeNumberField f : codeFieldContainer.codeField) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -3889,6 +4025,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No }); } + if (prevType == AUTH_TYPE_PHRASE) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringPhrase), true, dp(-1), dp(1))); + } else if (prevType == AUTH_TYPE_WORD) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringWord), true, dp(-1), dp(1))); + } else { + prevTypeTextView.setVisibility(View.GONE); + } + if (progressView != null) { progressView.setVisibility(nextType != 0 ? VISIBLE : GONE); } @@ -3929,16 +4075,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType != AUTH_TYPE_FRAGMENT_SMS) { if (currentType == AUTH_TYPE_MESSAGE) { if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { - problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone)); + problemText.setText(getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone)); } else if (nextType == AUTH_TYPE_FRAGMENT_SMS) { - problemText.setText(LocaleController.getString("DidNotGetTheCodeFragment", R.string.DidNotGetTheCodeFragment)); + problemText.setText(getString("DidNotGetTheCodeFragment", R.string.DidNotGetTheCodeFragment)); } else if (nextType == 0) { - problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); + problemText.setText(getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); } else { - problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms)); + problemText.setText(getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms)); } } else { - problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); + problemText.setText(getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); } } @@ -3960,13 +4106,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No problemText.setVisibility(VISIBLE); } } else if (currentType == AUTH_TYPE_FLASH_CALL) { - if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { setProblemTextVisible(false); timeText.setVisibility(VISIBLE); problemText.setVisibility(GONE); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0)); - } else if (nextType == AUTH_TYPE_SMS) { + } else if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); } } @@ -3975,11 +4121,15 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No onNextPressed(callLogNumber); } else if (catchedPhone != null) { onNextPressed(catchedPhone); - } else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + } else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { createTimer(); } - } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) { - timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 2, 0)); + } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) { + if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { + timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); + } else { + timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 2, 0)); + } setProblemTextVisible(time < 1000); timeText.setVisibility(time < 1000 ? GONE : VISIBLE); if (problemText != null) { @@ -4003,7 +4153,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { createTimer(); } - } else if (currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + } else if (currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 2, 0)); setProblemTextVisible(time < 1000); timeText.setVisibility(time < 1000 ? GONE : VISIBLE); @@ -4012,13 +4162,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } createTimer(); } else if (currentType == AUTH_TYPE_MISSED_CALL) { - if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { setProblemTextVisible(false); timeText.setVisibility(VISIBLE); problemText.setVisibility(GONE); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0)); - } else if (nextType == AUTH_TYPE_SMS) { + } else if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); } createTimer(); @@ -4050,104 +4200,6 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } - private class LoadingTextView extends TextView { - - private final Drawable rippleDrawable = Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), .10f), Theme.RIPPLE_MASK_ROUNDRECT_6DP); - public final LoadingDrawable loadingDrawable = new LoadingDrawable(); - - public LoadingTextView(Context context) { - super(context); - rippleDrawable.setCallback(this); - loadingDrawable.setAppearByGradient(true); - loadingDrawable.setSpeed(.8f); - } - - @Override - public void setText(CharSequence text, BufferType type) { - super.setText(text, type); - - updateLoadingLayout(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - updateLoadingLayout(); - } - - private void updateLoadingLayout() { - Layout layout = getLayout(); - if (layout == null) { - return; - } - CharSequence text = layout.getText(); - if (text == null) { - return; - } - LinkPath path = new LinkPath(true); - path.setInset(AndroidUtilities.dp(3), AndroidUtilities.dp(6)); - int start = 0; - int end = text.length(); - path.setCurrentLayout(layout, start, 0); - layout.getSelectionPath(start, end, path); - path.getBounds(AndroidUtilities.rectTmp); - rippleDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); - loadingDrawable.usePath(path); - loadingDrawable.setRadiiDp(4); - - int color = getThemedColor(Theme.key_chat_linkSelectBackground); - loadingDrawable.setColors( - Theme.multAlpha(color, 0.85f), - Theme.multAlpha(color, 2f), - Theme.multAlpha(color, 3.5f), - Theme.multAlpha(color, 6f) - ); - - loadingDrawable.updateBounds(); - } - - @Override - protected void onDraw(Canvas canvas) { - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - rippleDrawable.draw(canvas); - canvas.restore(); - - super.onDraw(canvas); - - if (isResendingCode || loadingDrawable.isDisappearing()) { - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - loadingDrawable.draw(canvas); - canvas.restore(); - invalidate(); - } - } - - @Override - protected boolean verifyDrawable(@NonNull Drawable who) { - return who == rippleDrawable || super.verifyDrawable(who); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (isRippleEnabled() && event.getAction() == MotionEvent.ACTION_DOWN) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - rippleDrawable.setHotspot(event.getX(), event.getY()); - } - rippleDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); - } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_UP) { - rippleDrawable.setState(new int[]{}); - } - return super.onTouchEvent(event); - } - - protected boolean isRippleEnabled() { - return true; - } - } - private void setProblemTextVisible(boolean visible) { if (problemText == null) { return; @@ -4229,9 +4281,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No int seconds = time / 1000 - minutes * 60; if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, minutes, seconds)); - } else if (currentType == AUTH_TYPE_SMS && nextType == AUTH_TYPE_SMS) { + } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { timeText.setText(LocaleController.formatString("ResendSmsAvailableIn", R.string.ResendSmsAvailableIn, minutes, seconds)); - } else if (nextType == AUTH_TYPE_SMS) { + } else if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, minutes, seconds)); } if (progressView != null && !progressView.isProgressAnimationRunning()) { @@ -4239,13 +4291,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } else { destroyTimer(); - if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { if (nextType == AUTH_TYPE_CALL) { - timeText.setText(LocaleController.getString("RequestCallButton", R.string.RequestCallButton)); + timeText.setText(getString("RequestCallButton", R.string.RequestCallButton)); } else if (nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FLASH_CALL) { - timeText.setText(LocaleController.getString("RequestMissedCall", R.string.RequestMissedCall)); + timeText.setText(getString("RequestMissedCall", R.string.RequestMissedCall)); } else { - timeText.setText(LocaleController.getString("RequestSmsButton", R.string.RequestSmsButton)); + timeText.setText(getString("RequestSmsButton", R.string.RequestSmsButton)); } timeText.setTextColor(Theme.getColor(Theme.key_chats_actionBackground)); timeText.setTag(R.id.color_key_tag, Theme.key_chats_actionBackground); @@ -4345,9 +4397,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {} new AlertDialog.Builder(getContext()) - .setTitle(LocaleController.getString(R.string.YourPasswordSuccess)) + .setTitle(getString(R.string.YourPasswordSuccess)) .setMessage(LocaleController.formatString(R.string.ChangePhoneNumberSuccessWithPhone, PhoneFormat.getInstance().format("+" + requestPhone))) - .setPositiveButton(LocaleController.getString(R.string.OK), null) + .setPositiveButton(getString(R.string.OK), null) .setOnDismissListener(dialog -> finishFragment()) .show(); }); @@ -4355,7 +4407,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No lastError = error.text; nextPressed = false; showDoneButton(false, true); - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { createTimer(); } if (currentType == AUTH_TYPE_FRAGMENT_SMS) { @@ -4371,18 +4423,18 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType != AUTH_TYPE_FLASH_CALL) { boolean isWrongCode = false; if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { shakeWrongCode(); isWrongCode = true; } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); } if (!isWrongCode) { @@ -4421,15 +4473,15 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } animateSuccess(() -> new AlertDialog.Builder(activity) - .setTitle(LocaleController.getString(R.string.CancelLinkSuccessTitle)) + .setTitle(getString(R.string.CancelLinkSuccessTitle)) .setMessage(LocaleController.formatString("CancelLinkSuccess", R.string.CancelLinkSuccess, PhoneFormat.getInstance().format("+" + phone))) - .setPositiveButton(LocaleController.getString(R.string.Close), null) + .setPositiveButton(getString(R.string.Close), null) .setOnDismissListener(dialog -> finishFragment()) .show()); } else { lastError = error.text; - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && - (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) || currentType == AUTH_TYPE_SMS && + (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { createTimer(); } if (currentType == AUTH_TYPE_FRAGMENT_SMS) { @@ -4505,7 +4557,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (error1 == null) { TLRPC.account_Password password = (TLRPC.account_Password) response1; if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); return; } Bundle bundle = new Bundle(); @@ -4518,7 +4570,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No animateSuccess(() -> setPage(VIEW_PASSWORD, true, bundle, false)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); destroyTimer(); @@ -4526,7 +4578,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { nextPressed = false; showDoneButton(false, true); - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { createTimer(); } if (currentType == AUTH_TYPE_FRAGMENT_SMS) { @@ -4545,18 +4597,18 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType != AUTH_TYPE_FLASH_CALL) { boolean isWrongCode = false; if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { shakeWrongCode(); isWrongCode = true; } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); } if (!isWrongCode) { @@ -4643,12 +4695,17 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return false; } + if (prevType != 0) { + setPage(prevType, true, null, true); + return false; + } + if (!force) { showDialog(new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString(R.string.EditNumber)) + .setTitle(getString(R.string.EditNumber)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("EditNumberInfo", R.string.EditNumberInfo, phone))) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setNegativeButton(LocaleController.getString(R.string.Edit), (dialogInterface, i) -> { + .setPositiveButton(getString(R.string.Close), null) + .setNegativeButton(getString(R.string.Edit), (dialogInterface, i) -> { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); }) @@ -4751,6 +4808,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No super.onHide(); isResendingCode = false; nextPressed = false; + if (prevType != 0 && currentParams != null) { + currentParams.putInt("timeout", time); + } } @Override @@ -4798,6 +4858,110 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } + + public class LoadingTextView extends TextView { + + private final Drawable rippleDrawable = Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), .10f), Theme.RIPPLE_MASK_ROUNDRECT_6DP); + public final LoadingDrawable loadingDrawable = new LoadingDrawable(); + + public LoadingTextView(Context context) { + super(context); + rippleDrawable.setCallback(this); + loadingDrawable.setAppearByGradient(true); + loadingDrawable.setSpeed(.8f); + } + + @Override + public void setText(CharSequence text, BufferType type) { + super.setText(text, type); + + updateLoadingLayout(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + updateLoadingLayout(); + } + + private void updateLoadingLayout() { + Layout layout = getLayout(); + if (layout == null) { + return; + } + CharSequence text = layout.getText(); + if (text == null) { + return; + } + LinkPath path = new LinkPath(true); + path.setInset(AndroidUtilities.dp(3), AndroidUtilities.dp(6)); + int start = 0; + int end = text.length(); + path.setCurrentLayout(layout, start, 0); + layout.getSelectionPath(start, end, path); + path.getBounds(AndroidUtilities.rectTmp); + rippleDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); + loadingDrawable.usePath(path); + loadingDrawable.setRadiiDp(4); + + int color = getThemedColor(Theme.key_chat_linkSelectBackground); + loadingDrawable.setColors( + Theme.multAlpha(color, 0.85f), + Theme.multAlpha(color, 2f), + Theme.multAlpha(color, 3.5f), + Theme.multAlpha(color, 6f) + ); + + loadingDrawable.updateBounds(); + } + + protected boolean isResendingCode() { + return false; + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + float offset = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : getPaddingTop(); + canvas.translate(getPaddingLeft(), offset); + rippleDrawable.draw(canvas); + canvas.restore(); + + super.onDraw(canvas); + + if (isResendingCode() || loadingDrawable.isDisappearing()) { + canvas.save(); + canvas.translate(getPaddingLeft(), offset); + loadingDrawable.draw(canvas); + canvas.restore(); + invalidate(); + } + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == rippleDrawable || super.verifyDrawable(who); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isRippleEnabled() && event.getAction() == MotionEvent.ACTION_DOWN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + rippleDrawable.setHotspot(event.getX(), event.getY()); + } + rippleDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); + } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_UP) { + rippleDrawable.setState(new int[]{}); + } + return super.onTouchEvent(event); + } + + protected boolean isRippleEnabled() { + return true; + } + } + public class LoginActivityPasswordView extends SlideView { private EditTextBoldCursor codeField; @@ -4832,7 +4996,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - titleView.setText(LocaleController.getString(R.string.YourPasswordHeader)); + titleView.setText(getString(R.string.YourPasswordHeader)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -4841,11 +5005,11 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); confirmTextView.setGravity(Gravity.CENTER_HORIZONTAL); confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - confirmTextView.setText(LocaleController.getString(R.string.LoginPasswordTextShort)); + confirmTextView.setText(getString(R.string.LoginPasswordTextShort)); addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12, 8, 12, 0)); outlineCodeField = new OutlineTextContainerView(context); - outlineCodeField.setText(LocaleController.getString(R.string.EnterPassword)); + outlineCodeField.setText(getString(R.string.EnterPassword)); codeField = new EditTextBoldCursor(context); codeField.setCursorSize(AndroidUtilities.dp(20)); codeField.setCursorWidth(1.5f); @@ -4873,7 +5037,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No cancelButton = new TextView(context); cancelButton.setGravity(Gravity.CENTER | Gravity.LEFT); - cancelButton.setText(LocaleController.getString(R.string.ForgotPassword)); + cancelButton.setText(getString(R.string.ForgotPassword)); cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); cancelButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); cancelButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); @@ -4918,9 +5082,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No run.end = endIndex + 1; emailPattern.setSpan(new TextStyleSpan(run), startIndex, endIndex + 1, 0); } - builder.setMessage(AndroidUtilities.formatSpannable(LocaleController.getString(R.string.RestoreEmailSent), emailPattern)); - builder.setTitle(LocaleController.getString("RestoreEmailSentTitle", R.string.RestoreEmailSentTitle)); - builder.setPositiveButton(LocaleController.getString(R.string.Continue), (dialogInterface, i) -> { + builder.setMessage(AndroidUtilities.formatSpannable(getString(R.string.RestoreEmailSent), emailPattern)); + builder.setTitle(getString("RestoreEmailSentTitle", R.string.RestoreEmailSentTitle)); + builder.setPositiveButton(getString(R.string.Continue), (dialogInterface, i) -> { Bundle bundle = new Bundle(); bundle.putString("email_unconfirmed_pattern", res.email_pattern); bundle.putString("password", passwordString); @@ -4943,19 +5107,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.WrongCodeTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.WrongCodeTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else { AndroidUtilities.hideKeyboard(codeField); new AlertDialog.Builder(context) - .setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)) - .setMessage(LocaleController.getString(R.string.RestorePasswordNoEmailText)) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setNegativeButton(LocaleController.getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)) + .setTitle(getString(R.string.RestorePasswordNoEmailTitle)) + .setMessage(getString(R.string.RestorePasswordNoEmailText)) + .setPositiveButton(getString(R.string.Close), null) + .setNegativeButton(getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)) .show(); } }); @@ -4975,7 +5139,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("LoginPassword", R.string.LoginPassword); + return getString("LoginPassword", R.string.LoginPassword); } @Override @@ -5087,9 +5251,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }); @@ -5205,8 +5369,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(R.string.ResetAccount)); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setText(getString(R.string.ResetAccount)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); innerLinearLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5221,7 +5385,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No resetAccountText = new TextView(context); resetAccountText.setGravity(Gravity.CENTER_HORIZONTAL); - resetAccountText.setText(LocaleController.getString("ResetAccountStatus", R.string.ResetAccountStatus)); + resetAccountText.setText(getString("ResetAccountStatus", R.string.ResetAccountStatus)); resetAccountText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); resetAccountText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(resetAccountText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 24, 0, 0)); @@ -5229,14 +5393,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No resetAccountTime = new TextView(context); resetAccountTime.setGravity(Gravity.CENTER_HORIZONTAL); resetAccountTime.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - resetAccountTime.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + resetAccountTime.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); resetAccountTime.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(resetAccountTime, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 8, 0, 0)); resetAccountButton = new TextView(context); resetAccountButton.setGravity(Gravity.CENTER); - resetAccountButton.setText(LocaleController.getString(R.string.ResetAccount)); - resetAccountButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + resetAccountButton.setText(getString(R.string.ResetAccount)); + resetAccountButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); resetAccountButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); resetAccountButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); resetAccountButton.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); @@ -5247,9 +5411,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } showDialog(new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)) - .setMessage(LocaleController.getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)) - .setPositiveButton(LocaleController.getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { + .setTitle(getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)) + .setMessage(getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)) + .setPositiveButton(getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { needShowProgress(0); TLRPC.TL_account_deleteAccount req = new TLRPC.TL_account_deleteAccount(); req.reason = "Forgot password"; @@ -5268,14 +5432,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No setPage(VIEW_REGISTER, true, params, false); } else { if (error.text.equals("2FA_RECENT_CONFIRM")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); }) - .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null).create()); + .setNegativeButton(getString("Cancel", R.string.Cancel), null).create()); }); } @@ -5290,7 +5454,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("ResetAccount", R.string.ResetAccount); + return getString("ResetAccount", R.string.ResetAccount); } private void updateTimeText() { @@ -5415,7 +5579,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.EnterNewEmail : R.string.AddEmailTitle)); + titleView.setText(getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.EnterNewEmail : R.string.AddEmailTitle)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5424,11 +5588,11 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitleView.setGravity(Gravity.CENTER); subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - subtitleView.setText(LocaleController.getString(R.string.AddEmailSubtitle)); + subtitleView.setText(getString(R.string.AddEmailSubtitle)); addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 8, 32, 0)); emailOutlineView = new OutlineTextContainerView(context); - emailOutlineView.setText(LocaleController.getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.YourNewEmail : R.string.YourEmail)); + emailOutlineView.setText(getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.YourNewEmail : R.string.YourEmail)); emailField = new EditTextBoldCursor(context); emailField.setCursorSize(AndroidUtilities.dp(20)); @@ -5474,7 +5638,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {} }, 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - str.append(LocaleController.getString(R.string.SignInWithGoogle)); + str.append(getString(R.string.SignInWithGoogle)); signInWithGoogleView.setText(str); loginOrView = new LoginOrView(context); @@ -5535,7 +5699,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("AddEmailTitle", R.string.AddEmailTitle); + return getString("AddEmailTitle", R.string.AddEmailTitle); } @Override @@ -5615,9 +5779,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No fillNextCodeParams(params, emailVerifiedLogin.sent_code); } else if (error != null) { if (error.text.contains("EMAIL_NOT_ALLOWED")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailNotAllowed)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailNotAllowed)); } else if (error.text.contains("EMAIL_TOKEN_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailTokenInvalid)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailTokenInvalid)); } else if (error.code != -1000) { AlertsCreator.processError(currentAccount, error, LoginActivity.this, verifyEmail); } @@ -5654,19 +5818,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (error.text.contains("EMAIL_INVALID")) { onPasscodeError(false); } else if (error.text.contains("EMAIL_NOT_ALLOWED")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailNotAllowed)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailNotAllowed)); } else if (error.text.contains("PHONE_PASSWORD_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.text.contains("PHONE_NUMBER_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.code != -1000) { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req, requestPhone); } @@ -5774,7 +5938,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.CheckYourNewEmail : setup ? R.string.VerificationCode : R.string.CheckYourEmail)); + titleView.setText(getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.CheckYourNewEmail : setup ? R.string.VerificationCode : R.string.CheckYourEmail)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5814,7 +5978,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {} }, 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - str.append(LocaleController.getString(R.string.SignInWithGoogle)); + str.append(getString(R.string.SignInWithGoogle)); signInWithGoogleView.setText(str); signInWithGoogleView.setOnClickListener(view -> { @@ -5858,7 +6022,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.AT_MOST)); } }; - cantAccessEmailView.setText(LocaleController.getString(R.string.LoginCantAccessThisEmail)); + cantAccessEmailView.setText(getString(R.string.LoginCantAccessThisEmail)); cantAccessEmailView.setGravity(Gravity.CENTER); cantAccessEmailView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); cantAccessEmailView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); @@ -5876,9 +6040,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } new AlertDialog.Builder(context) - .setTitle(LocaleController.getString(R.string.LoginEmailResetTitle)) - .setMessage(AndroidUtilities.formatSpannable(AndroidUtilities.replaceTags(LocaleController.getString(R.string.LoginEmailResetMessage)), email, getTimePattern(resetAvailablePeriod))) - .setPositiveButton(LocaleController.getString(R.string.LoginEmailResetButton), (dialog, which) -> { + .setTitle(getString(R.string.LoginEmailResetTitle)) + .setMessage(AndroidUtilities.formatSpannable(AndroidUtilities.replaceTags(getString(R.string.LoginEmailResetMessage)), email, getTimePattern(resetAvailablePeriod))) + .setPositiveButton(getString(R.string.LoginEmailResetButton), (dialog, which) -> { Bundle params = new Bundle(); params.putString("phone", phone); params.putString("ephone", emailPhone); @@ -5899,14 +6063,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); }) - .setNegativeButton(LocaleController.getString(R.string.Cancel), null) + .setNegativeButton(getString(R.string.Cancel), null) .show(); }); cantAccessEmailFrameLayout.addView(cantAccessEmailView); @@ -5932,7 +6096,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No resendCodeView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); resendCodeView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); resendCodeView.setMaxLines(2); - resendCodeView.setText(LocaleController.getString(R.string.ResendCode)); + resendCodeView.setText(getString(R.string.ResendCode)); resendCodeView.setOnClickListener(v -> { if (resendCodeView.getVisibility() != View.VISIBLE || resendCodeView.getAlpha() != 1f) { return; @@ -5984,7 +6148,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No errorViewSwitcher.addView(resendFrameLayout); wrongCodeView = new TextView(context); - wrongCodeView.setText(LocaleController.getString("WrongCode", R.string.WrongCode)); + wrongCodeView.setText(getString("WrongCode", R.string.WrongCode)); wrongCodeView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); wrongCodeView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); wrongCodeView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); @@ -6029,14 +6193,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else if (error != null && error.text != null) { if (error.text.contains("TASK_ALREADY_EXISTS")) { new AlertDialog.Builder(getContext()) - .setTitle(LocaleController.getString(R.string.LoginEmailResetPremiumRequiredTitle)) + .setTitle(getString(R.string.LoginEmailResetPremiumRequiredTitle)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.LoginEmailResetPremiumRequiredMessage, LocaleController.addNbsp(PhoneFormat.getInstance().format("+" + requestPhone))))) - .setPositiveButton(LocaleController.getString(R.string.OK), null) + .setPositiveButton(getString(R.string.OK), null) .show(); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req); } @@ -6087,7 +6251,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString(R.string.VerificationCode); + return getString(R.string.VerificationCode); } @Override @@ -6162,7 +6326,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No confirmText.setSpan(new TextStyleSpan(run), startIndex, endIndex + 1, 0); } - confirmTextView.setText(AndroidUtilities.formatSpannable(LocaleController.getString(R.string.CheckYourEmailSubtitle), confirmText)); + confirmTextView.setText(AndroidUtilities.formatSpannable(getString(R.string.CheckYourEmailSubtitle), confirmText)); } int v = params.getBoolean("googleSignInAllowed") && PushListenerController.GooglePushListenerServiceProvider.INSTANCE.hasServices() ? VISIBLE : GONE; @@ -6238,7 +6402,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No int timeRemaining = (int) (resetPendingDate - System.currentTimeMillis() / 1000L); if (resetPendingDate <= 0 || timeRemaining <= 0) { emailResetInView.setVisibility(VISIBLE); - emailResetInView.setText(LocaleController.getString(R.string.LoginEmailResetPleaseWait)); + emailResetInView.setText(getString(R.string.LoginEmailResetPleaseWait)); AndroidUtilities.runOnUIThread(this::requestEmailReset, 1000); return; } @@ -6394,7 +6558,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (error1 == null) { TLRPC.account_Password password = (TLRPC.account_Password) response1; if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); return; } Bundle bundle = new Bundle(); @@ -6407,7 +6571,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No animateSuccess(() -> setPage(VIEW_PASSWORD, true, bundle, false)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else { @@ -6415,22 +6579,22 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No showDoneButton(false, true); boolean isWrongCode = false; if (error.text.contains("EMAIL_ADDRESS_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailAddressInvalid)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailAddressInvalid)); } else if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("CODE_EMPTY") || error.text.contains("CODE_INVALID") || error.text.contains("EMAIL_CODE_INVALID") || error.text.contains("PHONE_CODE_INVALID")) { shakeWrongCode(); isWrongCode = true; } else if (error.text.contains("EMAIL_TOKEN_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailTokenInvalid)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailTokenInvalid)); } else if (error.text.contains("EMAIL_VERIFY_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); } if (!isWrongCode) { @@ -6575,8 +6739,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(R.string.EnterCode)); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setText(getString(R.string.EnterCode)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -6585,7 +6749,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); confirmTextView.setGravity(Gravity.CENTER); confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - confirmTextView.setText(LocaleController.getString(R.string.RestoreEmailSentInfo)); + confirmTextView.setText(getString(R.string.RestoreEmailSentInfo)); addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12, 8, 12, 0)); codeFieldContainer = new CodeFieldContainer(context) { @@ -6631,10 +6795,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No troubleButton.setOnClickListener(view -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("RestorePasswordNoEmailTitle", R.string.RestorePasswordNoEmailTitle)) - .setMessage(LocaleController.getString("RestoreEmailTroubleText", R.string.RestoreEmailTroubleText)) - .setPositiveButton(LocaleController.getString(R.string.OK), (dialogInterface, i) -> setPage(VIEW_PASSWORD, true, new Bundle(), true)) - .setNegativeButton(LocaleController.getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)); + .setTitle(getString("RestorePasswordNoEmailTitle", R.string.RestorePasswordNoEmailTitle)) + .setMessage(getString("RestoreEmailTroubleText", R.string.RestoreEmailTroubleText)) + .setPositiveButton(getString(R.string.OK), (dialogInterface, i) -> setPage(VIEW_PASSWORD, true, new Bundle(), true)) + .setNegativeButton(getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)); Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); @@ -6680,7 +6844,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("LoginPassword", R.string.LoginPassword); + return getString("LoginPassword", R.string.LoginPassword); } @Override @@ -6704,7 +6868,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No run.end = endIndex + 1; unconfirmedPattern.setSpan(new TextStyleSpan(run), startIndex, endIndex + 1, 0); } - troubleButton.setText(AndroidUtilities.formatSpannable(LocaleController.getString(R.string.RestoreEmailNoAccess), unconfirmedPattern)); + troubleButton.setText(AndroidUtilities.formatSpannable(getString(R.string.RestoreEmailNoAccess), unconfirmedPattern)); showKeyboard(codeFieldContainer); codeFieldContainer.requestFocus(); @@ -6782,9 +6946,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); @@ -6864,10 +7028,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleTextView = new TextView(context); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - titleTextView.setText(LocaleController.getString(R.string.SetNewPassword)); + titleTextView.setText(getString(R.string.SetNewPassword)); addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, AndroidUtilities.isSmallScreen() ? 16 : 72, 8, 0)); confirmTextView = new TextView(context); @@ -6879,7 +7043,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No for (int a = 0; a < codeField.length; a++) { OutlineTextContainerView outlineField = new OutlineTextContainerView(context); outlineFields[a] = outlineField; - outlineField.setText(LocaleController.getString(stage == 0 ? a == 0 ? R.string.PleaseEnterNewFirstPasswordHint : R.string.PleaseEnterNewSecondPasswordHint : R.string.PasswordHintPlaceholder)); + outlineField.setText(getString(stage == 0 ? a == 0 ? R.string.PleaseEnterNewFirstPasswordHint : R.string.PleaseEnterNewSecondPasswordHint : R.string.PasswordHintPlaceholder)); codeField[a] = new EditTextBoldCursor(context); codeField[a].setCursorSize(AndroidUtilities.dp(20)); @@ -6966,9 +7130,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } if (stage == 0) { - confirmTextView.setText(LocaleController.getString("PleaseEnterNewFirstPasswordLogin", R.string.PleaseEnterNewFirstPasswordLogin)); + confirmTextView.setText(getString("PleaseEnterNewFirstPasswordLogin", R.string.PleaseEnterNewFirstPasswordLogin)); } else { - confirmTextView.setText(LocaleController.getString("PasswordHintTextLogin", R.string.PasswordHintTextLogin)); + confirmTextView.setText(getString("PasswordHintTextLogin", R.string.PasswordHintTextLogin)); } cancelButton = new TextView(context); @@ -6976,7 +7140,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); cancelButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); cancelButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); - cancelButton.setText(LocaleController.getString(R.string.YourEmailSkip)); + cancelButton.setText(getString(R.string.YourEmailSkip)); FrameLayout bottomContainer = new FrameLayout(context); bottomContainer.addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, (Build.VERSION.SDK_INT >= 21 ? 56 : 60), Gravity.BOTTOM, 0, 0, 0, 32)); @@ -7022,7 +7186,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("NewPassword", R.string.NewPassword); + return getString("NewPassword", R.string.NewPassword); } @Override @@ -7118,13 +7282,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No needHideProgress(false); if (response instanceof TLRPC.auth_Authorization) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setPositiveButton(LocaleController.getString(R.string.Continue), (dialogInterface, i) -> onAuthSuccess((TLRPC.TL_auth_authorization) response)); + builder.setPositiveButton(getString(R.string.Continue), (dialogInterface, i) -> onAuthSuccess((TLRPC.TL_auth_authorization) response)); if (TextUtils.isEmpty(password)) { - builder.setMessage(LocaleController.getString(R.string.YourPasswordReset)); + builder.setMessage(getString(R.string.YourPasswordReset)); } else { - builder.setMessage(LocaleController.getString(R.string.YourPasswordChangedSuccessText)); + builder.setMessage(getString(R.string.YourPasswordChangedSuccessText)); } - builder.setTitle(LocaleController.getString(R.string.TwoStepVerificationTitle)); + builder.setTitle(getString(R.string.TwoStepVerificationTitle)); Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); @@ -7140,9 +7304,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }); @@ -7252,29 +7416,29 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("TermsOfService", R.string.TermsOfService)); + builder.setTitle(getString("TermsOfService", R.string.TermsOfService)); if (needAccept) { - builder.setPositiveButton(LocaleController.getString("Accept", R.string.Accept), (dialog, which) -> { + builder.setPositiveButton(getString("Accept", R.string.Accept), (dialog, which) -> { currentTermsOfService.popup = false; onNextPressed(null); }); - builder.setNegativeButton(LocaleController.getString("Decline", R.string.Decline), (dialog, which) -> { + builder.setNegativeButton(getString("Decline", R.string.Decline), (dialog, which) -> { AlertDialog.Builder builder1 = new AlertDialog.Builder(getParentActivity()); - builder1.setTitle(LocaleController.getString("TermsOfService", R.string.TermsOfService)); - builder1.setMessage(LocaleController.getString("TosDecline", R.string.TosDecline)); - builder1.setPositiveButton(LocaleController.getString("SignUp", R.string.SignUp), (dialog1, which1) -> { + builder1.setTitle(getString("TermsOfService", R.string.TermsOfService)); + builder1.setMessage(getString("TosDecline", R.string.TosDecline)); + builder1.setPositiveButton(getString("SignUp", R.string.SignUp), (dialog1, which1) -> { currentTermsOfService.popup = false; onNextPressed(null); }); - builder1.setNegativeButton(LocaleController.getString("Decline", R.string.Decline), (dialog12, which12) -> { + builder1.setNegativeButton(getString("Decline", R.string.Decline), (dialog12, which12) -> { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); }); showDialog(builder1.create()); }); } else { - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setPositiveButton(getString("OK", R.string.OK), null); } SpannableStringBuilder text = new SpannableStringBuilder(currentTermsOfService.text); @@ -7434,15 +7598,15 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No showAvatarProgress(false, false); titleTextView = new TextView(context); - titleTextView.setText(LocaleController.getString(R.string.RegistrationProfileInfo)); + titleTextView.setText(getString(R.string.RegistrationProfileInfo)); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.CENTER_HORIZONTAL); addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, 12, 8, 0)); descriptionTextView = new TextView(context); - descriptionTextView.setText(LocaleController.getString("RegisterText2", R.string.RegisterText2)); + descriptionTextView.setText(getString("RegisterText2", R.string.RegisterText2)); descriptionTextView.setGravity(Gravity.CENTER_HORIZONTAL); descriptionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); descriptionTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -7452,7 +7616,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No addView(editTextContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 8, 21, 8, 0)); firstNameOutlineView = new OutlineTextContainerView(context); - firstNameOutlineView.setText(LocaleController.getString(R.string.FirstName)); + firstNameOutlineView.setText(getString(R.string.FirstName)); firstNameField = new EditTextBoldCursor(context); firstNameField.setCursorSize(AndroidUtilities.dp(20)); @@ -7477,7 +7641,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No }); lastNameOutlineView = new OutlineTextContainerView(context); - lastNameOutlineView.setText(LocaleController.getString(R.string.LastName)); + lastNameOutlineView.setText(getString(R.string.LastName)); lastNameField = new EditTextBoldCursor(context); lastNameField.setCursorSize(AndroidUtilities.dp(20)); @@ -7503,7 +7667,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No buildEditTextLayout(AndroidUtilities.isSmallScreen()); wrongNumber = new TextView(context); - wrongNumber.setText(LocaleController.getString("CancelRegistration", R.string.CancelRegistration)); + wrongNumber.setText(getString("CancelRegistration", R.string.CancelRegistration)); wrongNumber.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_HORIZONTAL); wrongNumber.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); wrongNumber.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -7528,7 +7692,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No privacyLayout.addView(privacyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 56 : 60, Gravity.LEFT | Gravity.BOTTOM, 14, 0, 70, 32)); VerticalPositionAutoAnimator.attach(privacyView); - String str = LocaleController.getString("TermsOfServiceLogin", R.string.TermsOfServiceLogin); + String str = getString("TermsOfServiceLogin", R.string.TermsOfServiceLogin); SpannableStringBuilder text = new SpannableStringBuilder(str); int index1 = str.indexOf('*'); int index2 = str.lastIndexOf('*'); @@ -7565,8 +7729,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(HORIZONTAL); - firstNameOutlineView.setText(LocaleController.getString(R.string.FirstNameSmall)); - lastNameOutlineView.setText(LocaleController.getString(R.string.LastNameSmall)); + firstNameOutlineView.setText(getString(R.string.FirstNameSmall)); + lastNameOutlineView.setText(getString(R.string.LastNameSmall)); linearLayout.addView(firstNameOutlineView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f, 0, 0, 8, 0)); linearLayout.addView(lastNameOutlineView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f, 8, 0, 0, 0)); @@ -7581,8 +7745,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AndroidUtilities.showKeyboard(lastNameField); } } else { - firstNameOutlineView.setText(LocaleController.getString(R.string.FirstName)); - lastNameOutlineView.setText(LocaleController.getString(R.string.LastName)); + firstNameOutlineView.setText(getString(R.string.FirstName)); + lastNameOutlineView.setText(getString(R.string.LastName)); editTextContainer.addView(firstNameOutlineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 8, 0, 8, 0)); editTextContainer.addView(lastNameOutlineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 8, 82, 8, 0)); @@ -7659,14 +7823,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No public boolean onBackPressed(boolean force) { if (!force) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString(R.string.Warning)); - builder.setMessage(LocaleController.getString("AreYouSureRegistration", R.string.AreYouSureRegistration)); - builder.setNegativeButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { + builder.setTitle(getString(R.string.Warning)); + builder.setMessage(getString("AreYouSureRegistration", R.string.AreYouSureRegistration)); + builder.setNegativeButton(getString("Stop", R.string.Stop), (dialogInterface, i) -> { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); hidePrivacyView(); }); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); showDialog(builder.create()); return false; } @@ -7678,7 +7842,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public String getHeaderName() { - return LocaleController.getString("YourName", R.string.YourName); + return getString("YourName", R.string.YourName); } @Override @@ -7765,19 +7929,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { needHideProgress(false); if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.contains("FIRSTNAME_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidFirstName", R.string.InvalidFirstName)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidFirstName", R.string.InvalidFirstName)); } else if (error.text.contains("LASTNAME_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidLastName", R.string.InvalidLastName)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidLastName", R.string.InvalidLastName)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); @@ -8007,9 +8171,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setMessage(LocaleController.getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)); - builder.setTitle(LocaleController.getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)); - builder.setPositiveButton(LocaleController.getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { + builder.setMessage(getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)); + builder.setTitle(getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)); + builder.setPositiveButton(getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { needShowProgress(0); TLRPC.TL_account_deleteAccount req = new TLRPC.TL_account_deleteAccount(); req.reason = "Forgot password"; @@ -8027,7 +8191,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No setPage(VIEW_REGISTER, true, params, false); } else { if (error.text.equals("2FA_RECENT_CONFIRM")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); } else if (error.text.startsWith("2FA_CONFIRM_WAIT_")) { Bundle params = new Bundle(); params.putString("phoneFormated", requestPhone); @@ -8037,12 +8201,12 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No params.putInt("waitTime", Utilities.parseInt(error.text.replace("2FA_CONFIRM_WAIT_", ""))); setPage(VIEW_RESET_WAIT, true, params, false); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } @@ -8097,7 +8261,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No floatingProgressView.setScaleY(0.1f); popupFabContainer.addView(floatingProgressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - popupFabContainer.setContentDescription(LocaleController.getString(R.string.Done)); + popupFabContainer.setContentDescription(getString(R.string.Done)); addView(popupFabContainer, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60)); popupLayout = new FrameLayout(context); @@ -8105,7 +8269,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No addView(popupLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 140, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 24, 0, 24, 0)); confirmMessageView = new TextView(context); - confirmMessageView.setText(LocaleController.getString(R.string.ConfirmCorrectNumber)); + confirmMessageView.setText(getString(R.string.ConfirmCorrectNumber)); confirmMessageView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); confirmMessageView.setSingleLine(); popupLayout.addView(confirmMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 24, 20, 24, 0)); @@ -8113,7 +8277,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No numberView = new TextView(context); numberView.setText(numberText); numberView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - numberView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + numberView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); numberView.setSingleLine(); popupLayout.addView(numberView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 24, 48, 24, 0)); @@ -8121,7 +8285,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No int buttonMargin = 8; editTextView = new TextView(context); - editTextView.setText(LocaleController.getString(R.string.Edit)); + editTextView.setText(getString(R.string.Edit)); editTextView.setSingleLine(); editTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); editTextView.setBackground(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_changephoneinfo_image2))); @@ -8131,7 +8295,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No popupLayout.addView(editTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), buttonMargin, buttonMargin, buttonMargin, buttonMargin)); confirmTextView = new TextView(context); - confirmTextView.setText(LocaleController.getString(R.string.CheckPhoneNumberYes)); + confirmTextView.setText(getString(R.string.CheckPhoneNumberYes)); confirmTextView.setSingleLine(); confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); confirmTextView.setBackground(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_changephoneinfo_image2))); @@ -8378,4 +8542,938 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No updateProxyButton(true, false); } } + + + public class LoginActivityPhraseView extends SlideView { + + private final @AuthType int currentType; + + private final LinearLayout fieldContainer; + private final OutlineTextContainerView outlineField; + private final EditTextBoldCursor codeField; + private final FrameLayout infoContainer; + private final TextView prevTypeTextView; + private final TextView errorTextView; + private final TextView infoTextView; + private final RLottieImageView imageView; + private final TextView titleTextView; + private final TextView confirmTextView; + private final TextView pasteTextView; + private final LoadingTextView timeText; +// private TextView cancelButton; + private boolean pasteShown = true; + private boolean errorShown = false; + private boolean pasting = false, pasted = false; + + private @AuthType int nextType; + private @AuthType int prevType; + private String requestPhone, phoneHash, emailPhone, phone; + private String beginning; + private Bundle currentParams; + + private boolean isResendingCode; + private Timer timeTimer; + private Timer codeTimer; + private int openTime; + private final Object timerSync = new Object(); + private int time = 60000; + private int codeTime = 15000; + private double lastCurrentTime; + private double lastCodeTime; + private boolean ignoreOnTextChange; + private boolean waitingForEvent; + private boolean nextPressed; + private String lastError = ""; + + private Bundle nextCodeParams; + private TLRPC.TL_auth_sentCode nextCodeAuth; + + public LoginActivityPhraseView(Context context, @AuthType int type) { + super(context); + currentType = type; + final int a; + if (type == AUTH_TYPE_WORD) { + a = 0; + } else /* if (type == AUTH_TYPE_PHRASE) */ { + a = 1; + } + + setOrientation(VERTICAL); + + imageView = new RLottieImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setAnimation(R.raw.bubble, 95, 95); + boolean hideImage = AndroidUtilities.isSmallScreen() || (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y && !AndroidUtilities.isTablet()); + imageView.setVisibility(hideImage ? GONE : VISIBLE); + addView(imageView, LayoutHelper.createLinear(95, 95, Gravity.CENTER_HORIZONTAL, 0, 10, 0, 5)); + + titleTextView = new TextView(context); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); + titleTextView.setText(getString(a == 0 ? R.string.SMSWordTitle : R.string.SMSPhraseTitle)); + addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, hideImage ? 25 : 0, 8, 0)); + + confirmTextView = new TextView(context); + confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + confirmTextView.setGravity(Gravity.CENTER_HORIZONTAL); + confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, 5, 8, 16)); + + outlineField = new OutlineTextContainerView(context); + outlineField.setText(getString(a == 0 ? R.string.SMSWord : R.string.SMSPhrase)); + + codeField = new EditTextBoldCursor(context) { + @Override + public boolean onTextContextMenuItem(int id) { + switch (id) { + case android.R.id.paste: + case android.R.id.pasteAsPlainText: + pasting = pasted = true; + postDelayed(() -> pasting = false, 1000); + break; + } + return super.onTextContextMenuItem(id); + } + }; + codeField.setSingleLine(); + codeField.setLines(1); + codeField.setCursorSize(AndroidUtilities.dp(20)); + codeField.setCursorWidth(1.5f); + codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + codeField.setMaxLines(1); + codeField.setBackground(null); + codeField.setHint(getString(a == 0 ? R.string.SMSWordHint : R.string.SMSPhraseHint)); + codeField.addTextChangedListener(new TextWatcher() { + private boolean ignoreTextChange; + private int trimmedLength; + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (ignoreTextChange) return; + if (s == null || beginning == null) return; + trimmedLength = trimLeft(s.toString()).length(); + } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (ignoreTextChange) return; + } + @Override + public void afterTextChanged(Editable s) { + if (ignoreTextChange) return; + checkPaste(true); + AndroidUtilities.cancelRunOnUIThread(dismissField); + animateError(false); + if (TextUtils.isEmpty(s)) { + pasted = false; + } + if (!beginsOk(s.toString())) { + onInputError(true); + ignoreTextChange = true; + boolean selectedEnd = codeField.getSelectionEnd() >= codeField.getText().length(); + if (!pasted) { + codeField.setText(beginning.substring(0, Utilities.clamp(trimmedLength, beginning.length(), 0))); + if (selectedEnd) { + codeField.setSelection(codeField.getText().length()); + } + } + ignoreTextChange = false; + } + } + }); + codeField.setEllipsizeByGradient(true); + codeField.setInputType(InputType.TYPE_CLASS_TEXT); + + codeField.setTypeface(Typeface.DEFAULT); + codeField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + + codeField.setOnFocusChangeListener((v, hasFocus) -> outlineField.animateSelection(hasFocus ? 1f : 0f)); + + pasteTextView = new TextView(context); + pasteTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + pasteTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + pasteTextView.setText(getString(R.string.Paste)); + pasteTextView.setPadding(dp(10), 0, dp(10), 0); + pasteTextView.setGravity(Gravity.CENTER); + int textColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourceProvider); + pasteTextView.setTextColor(textColor); + pasteTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(6), Theme.multAlpha(textColor, .12f), Theme.multAlpha(textColor, .15f))); + ScaleStateListAnimator.apply(pasteTextView, .1f, 1.5f); + codeField.setPadding(dp(16), dp(16 - 2.66f), dp(16), dp(16 - 2.66f)); + pasteTextView.setOnClickListener(v -> { + ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + CharSequence text = null; + try { + text = clipboardManager.getPrimaryClip().getItemAt(0).coerceToText(getContext()); + } catch (Exception e) { + FileLog.e(e); + } + if (text != null) { + Editable fieldText = codeField.getText(); + pasting = pasted = true; + if (fieldText != null) { + final int start = Math.max(0, codeField.getSelectionStart()); + final int end = Math.max(start, codeField.getSelectionEnd()); + fieldText.replace(start, end, text); + } + pasting = false; + } + checkPaste(true); + }); + + outlineField.addView(codeField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 0, 0, 0, 0)); + outlineField.attachEditText(codeField); + outlineField.addView(pasteTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 26, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 10, 0)); + + fieldContainer = new LinearLayout(context); + fieldContainer.setOrientation(VERTICAL); + fieldContainer.addView(outlineField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); + addView(fieldContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 16, 3, 16, 0)); + codeField.setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_NEXT) { + onNextPressed(null); + return true; + } + return false; + }); + + infoContainer = new FrameLayout(context); + fieldContainer.addView(infoContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + prevTypeTextView = new LoadingTextView(context); + prevTypeTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + prevTypeTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + prevTypeTextView.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); + prevTypeTextView.setOnClickListener(v -> onBackPressed(true)); + addView(prevTypeTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 18, 0, 0)); + prevTypeTextView.setVisibility(View.GONE); + + errorTextView = new TextView(context); + errorTextView.setPivotX(0); + errorTextView.setPivotY(0); + errorTextView.setText(getString(a == 0 ? R.string.SMSWordError : R.string.SMSPhraseError)); + errorTextView.setTextColor(getThemedColor(Theme.key_text_RedRegular)); + errorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + infoContainer.addView(errorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 16, 8, 16, 8)); + errorTextView.setAlpha(0f); + errorTextView.setScaleX(.8f); + errorTextView.setScaleY(.8f); + errorTextView.setTranslationY(-dp(4)); + + infoTextView = new TextView(context); + infoTextView.setPivotX(0); + infoTextView.setPivotY(0); + infoTextView.setText(getString(a == 0 ? R.string.SMSWordPasteHint : R.string.SMSPhrasePasteHint)); + infoTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + infoContainer.addView(infoTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 16, 8, 16, 8)); + + timeText = new LoadingTextView(context) { + @Override + protected boolean isResendingCode() { + return isResendingCode; + } + @Override + protected boolean isRippleEnabled() { + return getVisibility() == View.VISIBLE && !(time > 0 && timeTimer != null); + } + }; + timeText.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + timeText.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + timeText.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + timeText.setOnClickListener(v -> { +// if (isRequestingFirebaseSms || isResendingCode) { +// return; +// } + if (time > 0 && timeTimer != null) { + return; + } + if (nextCodeParams != null && nextCodeAuth != null) { + fillNextCodeParams(nextCodeParams, nextCodeAuth); + return; + } + + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { + isResendingCode = true; + timeText.invalidate(); + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); +// timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setText(getString(R.string.Calling)); + } else { + timeText.setText(getString(R.string.SendingSms)); + } + Bundle params = new Bundle(); + params.putString("phone", phone); + params.putString("ephone", emailPhone); + params.putString("phoneFormated", requestPhone); + params.putInt("prevType", currentType); + +// createCodeTimer(); + TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + isResendingCode = false; + timeText.invalidate(); + if (response != null) { + nextCodeParams = params; + nextCodeAuth = (TLRPC.TL_auth_sentCode) response; + fillNextCodeParams(nextCodeParams, nextCodeAuth); + } else if (error != null && error.text != null) { + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidCode)); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.FloodWait)); + } else if (error.code != -1000) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.ErrorOccurred) + "\n" + error.text); + } + lastError = error.text; + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + } else if (nextType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.setWaitingForSms(false); +// NotificationCenter.getGlobalInstance().removeObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); + waitingForEvent = false; +// destroyCodeTimer(); + resendCode(); + } + }); + +// cancelButton = new TextView(context); +// cancelButton.setGravity(Gravity.CENTER | Gravity.LEFT); +// cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); +// cancelButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); +// cancelButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); +// cancelButton.setText(getString(R.string.YourEmailSkip)); + + FrameLayout bottomContainer = new FrameLayout(context); + bottomContainer.addView(timeText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, (Build.VERSION.SDK_INT >= 21 ? 56 : 60), Gravity.BOTTOM, 6, 0, 60, 28)); + addView(bottomContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM)); + VerticalPositionAutoAnimator.attach(timeText); + +// cancelButton.setOnClickListener(view -> { +// +// }); + } + + private final Runnable checkPasteRunnable = () -> checkPaste(true); + + private void checkPaste(boolean animated) { + AndroidUtilities.cancelRunOnUIThread(checkPasteRunnable); + + boolean show; + ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + show = TextUtils.isEmpty(codeField.getText()) && clipboardManager != null && clipboardManager.hasPrimaryClip(); + + if (pasteShown != show) { + pasteShown = show; + if (animated) { + pasteTextView.animate() + .alpha(show ? 1f : 0f) + .scaleX(show ? 1f : .7f) + .scaleY(show ? 1f : .7f) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .setDuration(300) + .start(); + + infoTextView.animate() + .scaleX(pasteShown && !errorShown ? 1f : .9f) + .scaleY(pasteShown && !errorShown ? 1f : .9f) + .alpha(pasteShown && !errorShown ? 1f : 0f) + .translationY(pasteShown && !errorShown ? 0 : dp(errorShown ? 5 : -5)) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .setDuration(300) + .start(); + } else { + pasteTextView.setAlpha(show ? 1f : 0f); + pasteTextView.setScaleX(show ? 1f : .7f); + pasteTextView.setScaleY(show ? 1f : .7f); + + infoTextView.setScaleX(pasteShown && !errorShown ? 1f : .9f); + infoTextView.setScaleY(pasteShown && !errorShown ? 1f : .9f); + infoTextView.setAlpha(pasteShown && !errorShown ? 1f : 0f); + infoTextView.setTranslationY(pasteShown && !errorShown ? 0 : dp(errorShown ? 5 : -5)); + } + } + + AndroidUtilities.runOnUIThread(checkPasteRunnable, 1000 * 5); + } + + @Override + public void updateColors() { + titleTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + confirmTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText6)); + codeField.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + codeField.setCursorColor(getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated)); + codeField.setHintTextColor(getThemedColor(Theme.key_windowBackgroundWhiteHintText)); + outlineField.updateColor(); +// cancelButton.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + } + + @Override + public boolean needBackButton() { + return true; + } + + @Override + public void onCancelPressed() { + nextPressed = false; + } + + @Override + public String getHeaderName() { + return getString("NewPassword", R.string.NewPassword); + } + + @Override + public void setParams(Bundle params, boolean restore) { + if (params == null) { + if (nextCodeParams != null && nextCodeAuth != null) { + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + int resId; + if (nextType == AUTH_TYPE_PHRASE) { + resId = R.string.ReturnEnteringPhrase; + } else if (nextType == AUTH_TYPE_WORD) { + resId = R.string.ReturnEnteringWord; + } else { + resId = R.string.ReturnEnteringSMS; + } + timeText.setText(AndroidUtilities.replaceArrows(getString(resId), true, dp(1), dp(1))); + } + return; + } + codeField.setText(""); + currentParams = params; + beginning = null; + nextType = params.getInt("nextType"); + prevType = params.getInt("prevType", 0); + emailPhone = params.getString("ephone"); + if (currentParams.containsKey("beginning")) { + beginning = currentParams.getString("beginning"); + } + requestPhone = params.getString("phoneFormated"); + phoneHash = params.getString("phoneHash"); + phone = currentParams.getString("phone"); + time = params.getInt("timeout"); + + if (prevType == AUTH_TYPE_PHRASE) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringPhrase), true, dp(-1), dp(1))); + } else if (prevType == AUTH_TYPE_WORD) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringWord), true, dp(-1), dp(1))); + } else if (prevType == AUTH_TYPE_MESSAGE || prevType == AUTH_TYPE_SMS || prevType == AUTH_TYPE_CALL || prevType == AUTH_TYPE_FLASH_CALL || prevType == AUTH_TYPE_FRAGMENT_SMS) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringCode), true, dp(-1), dp(1))); + } else { + prevTypeTextView.setVisibility(View.GONE); + } + + nextCodeParams = null; + nextCodeAuth = null; + nextPressed = false; + isResendingCode = false; + isRequestingFirebaseSms = false; + timeText.invalidate(); + + final int a = currentType == AUTH_TYPE_WORD ? 0 : 1; + final String formattedPhone = "+" + PhoneFormat.getInstance().format(PhoneFormat.stripExceptNumbers(phone)); + if (beginning == null) { + confirmTextView.setText(AndroidUtilities.replaceTags(formatString(a == 0 ? R.string.SMSWordText : R.string.SMSPhraseText, formattedPhone))); + } else { + confirmTextView.setText(AndroidUtilities.replaceTags(formatString(a == 0 ? R.string.SMSWordBeginningText : R.string.SMSPhraseBeginningText, formattedPhone, beginning))); + } + + showKeyboard(codeField); + codeField.requestFocus(); + + if (imageView.getAnimatedDrawable() != null) { + imageView.getAnimatedDrawable().setCurrentFrame(0, false); + } + AndroidUtilities.runOnUIThread(imageView::playAnimation, 500); + + checkPaste(false); + animateError(false); + + lastCurrentTime = System.currentTimeMillis(); + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) { + createTimer(); + } else { + timeText.setVisibility(GONE); + } + } + + private void animateError(boolean show) { + errorShown = show; + float value = show ? 1f : 0f; + outlineField.animateError(value); + errorTextView.animate().scaleX(.9f + .1f * value).scaleY(.9f + .1f * value).alpha(value).translationY((1f - value) * dp(-5)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(290).start(); + + boolean showPaste = pasteShown && !errorShown; + value = showPaste ? 1f : 0f; + infoTextView.animate().scaleX(.9f + .1f * value).scaleY(.9f + .1f * value).alpha(value).translationY((1f - value) * dp(errorShown ? 5 : -5)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(290).start(); + } + + private final Runnable dismissField = () -> animateError(false); + + private float shiftDp = -3; + private void onInputError(boolean asBeginning) { + if (getParentActivity() == null) { + return; + } + try { + codeField.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) {} + final int a = currentType == AUTH_TYPE_WORD ? 0 : 1; + if (asBeginning) { + errorTextView.setText(getString(a == 0 ? R.string.SMSWordBeginningError : R.string.SMSPhraseBeginningError)); + } else if (TextUtils.isEmpty(codeField.getText())) { + errorTextView.setText(""); + } else { + errorTextView.setText(getString(a == 0 ? R.string.SMSWordError : R.string.SMSPhraseError)); + } + if (!errorShown && !pasted) { + AndroidUtilities.shakeViewSpring(codeField, shiftDp); + AndroidUtilities.shakeViewSpring(errorTextView, shiftDp); + } + AndroidUtilities.cancelRunOnUIThread(dismissField); + animateError(true); + AndroidUtilities.runOnUIThread(dismissField, 10_000); + shiftDp = -shiftDp; + } + + @Override + public void onNextPressed(String code) { + if (nextPressed) { + return; + } + + code = codeField.getText().toString(); + if (code.length() == 0) { + onInputError(false); + return; + } + + if (!beginsOk(code)) { + onInputError(true); + return; + } + + nextPressed = true; + + TLRPC.TL_auth_signIn req = new TLRPC.TL_auth_signIn(); + req.phone_number = requestPhone; + req.phone_code = code; + req.phone_code_hash = phoneHash; + req.flags |= 1; + int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + needHideProgress(false, true); + + boolean ok = false; + + if (error == null) { + nextPressed = false; + ok = true; + showDoneButton(false, true); + destroyTimer(); +// destroyCodeTimer(); + if (response instanceof TLRPC.TL_auth_authorizationSignUpRequired) { + TLRPC.TL_auth_authorizationSignUpRequired authorization = (TLRPC.TL_auth_authorizationSignUpRequired) response; + if (authorization.terms_of_service != null) { + currentTermsOfService = authorization.terms_of_service; + } + Bundle params = new Bundle(); + params.putString("phoneFormated", requestPhone); + params.putString("phoneHash", phoneHash); + params.putString("code", req.phone_code); + + setPage(VIEW_REGISTER, true, params, false); + } else { + onAuthSuccess((TLRPC.TL_auth_authorization) response); + } + } else { + lastError = error.text; + if (error.text.contains("SESSION_PASSWORD_NEEDED")) { + ok = true; + TLRPC.TL_account_getPassword req2 = new TLRPC.TL_account_getPassword(); + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { + nextPressed = false; + showDoneButton(false, true); + if (error1 == null) { + TLRPC.account_Password password = (TLRPC.account_Password) response1; + if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + return; + } + Bundle bundle = new Bundle(); + SerializedData data = new SerializedData(password.getObjectSize()); + password.serializeToStream(data); + bundle.putString("password", Utilities.bytesToHex(data.toByteArray())); + bundle.putString("phoneFormated", requestPhone); + bundle.putString("phoneHash", phoneHash); + bundle.putString("code", req.phone_code); + + setPage(VIEW_PASSWORD, true, bundle, false); + } else { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + destroyTimer(); +// destroyCodeTimer(); + } else { + nextPressed = false; +// showDoneButton(true, true); +// if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { +// createTimer(); +// } + if (currentType != AUTH_TYPE_FLASH_CALL) { + boolean isWrongCode = false; + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + onInputError(false); + isWrongCode = true; + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); + } else { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + } + + if (isWrongCode) { + codeField.post(() -> { + codeField.requestFocus(); + if (beginning != null && beginning.length() > 1) { + String text = codeField.getText().toString(); + int select = trimLeftLen(text) + beginning.length(); + boolean nextIsSpace = select >= 0 && select < text.length() && text.charAt(select) == ' '; + codeField.setSelection(Utilities.clamp(select + (nextIsSpace ? 1 : 0), text.length(), 0), codeField.getText().length()); + } else { + codeField.setSelection(0, codeField.getText().length()); + } + }); + } else { + codeField.setText(""); + codeField.requestFocus(); + } + } + } + } + if (ok) { + if (currentType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.endIncomingCall(); + AndroidUtilities.setWaitingForCall(false); + } + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + needShowProgress(reqId, true); + showDoneButton(true, true); + } + + + private void resendCode() { + if (nextPressed || isResendingCode || isRequestingFirebaseSms) { + return; + } + + isResendingCode = true; + timeText.invalidate(); + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); +// problemText.invalidate(); + + final Bundle params = new Bundle(); + params.putString("phone", phone); + params.putString("ephone", emailPhone); + params.putString("phoneFormated", requestPhone); + + nextPressed = true; + + TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + nextPressed = false; + if (error == null) { + fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); + } else { + if (error.text != null) { + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidCode)); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.FloodWait)); + } else if (error.code != -1000) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.ErrorOccurred) + "\n" + error.text); + } + } + } + needHideProgress(false); + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + needShowProgress(reqId); + } + + @Override + public boolean onBackPressed(boolean force) { + needHideProgress(true); + if (prevType != 0) { + setPage(prevType, true, null, true); + return false; + } + currentParams = null; + nextPressed = false; + return true; + } + + @Override + public void onResume() { + super.onResume(); + checkPaste(true); + } + + @Override + public void onShow() { + super.onShow(); + AndroidUtilities.runOnUIThread(() -> { + if (codeField != null) { + codeField.requestFocus(); + codeField.setSelection(codeField.length()); + AndroidUtilities.showKeyboard(codeField); + } + }, SHOW_DELAY); + } + + @Override + public void onHide() { + super.onHide(); + AndroidUtilities.cancelRunOnUIThread(checkPasteRunnable); + } + + @Override + public void saveStateParams(Bundle bundle) { + if (currentParams != null) { + bundle.putBundle("recoveryview_word" + currentType, currentParams); + } + } + + @Override + public void restoreStateParams(Bundle bundle) { + currentParams = bundle.getBundle("recoveryview_word" + currentType); + if (currentParams != null) { + setParams(currentParams, true); + } + } + +// private void setProblemTextVisible(boolean visible) { +// if (problemText == null) { +// return; +// } +// float newAlpha = visible ? 1f : 0f; +// if (problemText.getAlpha() != newAlpha) { +// problemText.animate().cancel(); +// problemText.animate().alpha(newAlpha).setDuration(150).start(); +// } +// } +// +// private void createCodeTimer() { +// if (codeTimer != null) { +// return; +// } +// codeTime = 15000; +// if (time > codeTime) { +// codeTime = time; +// } +// codeTimer = new Timer(); +// lastCodeTime = System.currentTimeMillis(); +// codeTimer.schedule(new TimerTask() { +// @Override +// public void run() { +// AndroidUtilities.runOnUIThread(() -> { +// double currentTime = System.currentTimeMillis(); +// double diff = currentTime - lastCodeTime; +// lastCodeTime = currentTime; +// codeTime -= diff; +// if (codeTime <= 1000) { +// setProblemTextVisible(true); +// timeText.setVisibility(GONE); +// if (problemText != null) { +// problemText.setVisibility(VISIBLE); +// } +// destroyCodeTimer(); +// } +// }); +// } +// }, 0, 1000); +// } + +// +// private void destroyCodeTimer() { +// try { +// synchronized (timerSync) { +// if (codeTimer != null) { +// codeTimer.cancel(); +// codeTimer = null; +// } +// } +// } catch (Exception e) { +// FileLog.e(e); +// } +// } + + private void createTimer() { + if (timeTimer != null) { + return; + } + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + timeText.setTag(R.id.color_key_tag, Theme.key_windowBackgroundWhiteGrayText); +// if (progressView != null) { +// progressView.resetProgressAnimation(); +// } + timeTimer = new Timer(); + timeTimer.schedule(new TimerTask() { + @Override + public void run() { + if (timeTimer == null) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + double currentTime = System.currentTimeMillis(); + double diff = currentTime - lastCurrentTime; + lastCurrentTime = currentTime; + time -= diff; + if (time >= 1000) { + int minutes = time / 1000 / 60; + int seconds = time / 1000 - minutes * 60; + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setText(LocaleController.formatString(R.string.CallAvailableIn2, minutes, seconds)); + } else if (nextType == AUTH_TYPE_SMS) { + timeText.setText(LocaleController.formatString(R.string.SmsAvailableIn2, minutes, seconds)); + } +// if (progressView != null && !progressView.isProgressAnimationRunning()) { +// progressView.startProgressAnimation(time - 1000L); +// } + } else { + destroyTimer(); + if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + if (nextType == AUTH_TYPE_CALL) { + timeText.setText(getString(R.string.RequestCallButton)); + } else if (nextType == AUTH_TYPE_FRAGMENT_SMS) { + timeText.setText(getString(R.string.DidNotGetTheCodeFragment)); + } else if (nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FLASH_CALL) { + timeText.setText(getString(R.string.RequestMissedCall)); + } else { + timeText.setText(replaceArrows(getString(R.string.RequestAnotherSMS), true, 0, 0)); + } + timeText.setTextColor(Theme.getColor(Theme.key_chats_actionBackground)); + timeText.setTag(R.id.color_key_tag, Theme.key_chats_actionBackground); + } + } + }); + } + }, 0, 1000); + } + + private void destroyTimer() { + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + timeText.setTag(R.id.color_key_tag, Theme.key_windowBackgroundWhiteGrayText); + try { + synchronized (timerSync) { + if (timeTimer != null) { + timeTimer.cancel(); + timeTimer = null; + } + } + } catch (Exception e) { + FileLog.e(e); + } + } + + private boolean beginsOk(String text) { + if (beginning == null) { + return true; + } + String lt = trimLeft(text).toLowerCase(); + String lb = beginning.toLowerCase(); + int len = Math.min(lt.length(), lb.length()); + if (len <= 0) return true; + return TextUtils.equals(lt.substring(0, len), lb.substring(0, len)); + } + + private int trimLeftLen(String str) { + int len = str.length(); + int st = 0; + while ((st < len) && (str.charAt(st) <= ' ')) { + st++; + } + return st; + } + + private String trimLeft(String str) { + int len = str.length(); + int st = 0; + + while ((st < len) && (str.charAt(st) <= ' ')) { + st++; + } +// while ((st < len) && (str.charAt(len - 1) <= ' ')) { +// len--; +// } + return ((st > 0) || (len < str.length())) ? str.substring(st, len) : str; + } + } + + @Override + public void clearViews() { + if (fragmentView != null) { + ViewGroup parent = (ViewGroup) fragmentView.getParent(); + if (parent != null) { + try { + onRemoveFromParent(); + parent.removeViewInLayout(fragmentView); + } catch (Exception e) { + FileLog.e(e); + } + } + if (pendingSwitchingAccount) { + cachedFragmentView = fragmentView; + } + fragmentView = null; + } + if (actionBar != null && !pendingSwitchingAccount) { + ViewGroup parent = (ViewGroup) actionBar.getParent(); + if (parent != null) { + try { + parent.removeViewInLayout(actionBar); + } catch (Exception e) { + FileLog.e(e); + } + } + actionBar = null; + } + clearStoryViewers(); + parentLayout = null; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index d7b32bbf1..8ec1bb975 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -8,9 +8,13 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; import static org.telegram.messenger.NotificationsController.TYPE_CHANNEL; import static org.telegram.messenger.NotificationsController.TYPE_GROUP; import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_MESSAGES; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_STORIES; import static org.telegram.messenger.NotificationsController.TYPE_STORIES; import android.animation.Animator; @@ -22,6 +26,8 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; @@ -30,11 +36,14 @@ import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; import android.util.LongSparseArray; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.OvershootInterpolator; import android.widget.EditText; import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.recyclerview.widget.DefaultItemAnimator; @@ -53,6 +62,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLObject; @@ -68,6 +78,7 @@ import org.telegram.ui.Adapters.SearchAdapterHelper; import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.NotificationsCheckCell; +import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; @@ -107,6 +118,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements private final static int search_button = 0; + private int settingsStart, settingsEnd; private int exceptionsStart, exceptionsEnd; private boolean showAutoExceptions = true; @@ -260,6 +272,8 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements case TYPE_GROUP: color = getNotificationsSettings().getInt("GroupLed", color); break; case TYPE_STORIES: color = getNotificationsSettings().getInt("StoriesLed", color); break; case TYPE_CHANNEL: color = getNotificationsSettings().getInt("ChannelLed", color); break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: color = getNotificationsSettings().getInt("ReactionsLed", color); break; } for (int a = 0; a < 9; a++) { if (TextColorCell.colorsToSave[a] == color) { @@ -277,12 +291,12 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements case TYPE_GROUP: option = getNotificationsSettings().getInt("popupGroup", 0); break; case TYPE_CHANNEL: option = getNotificationsSettings().getInt("popupChannel", 0); break; } - return LocaleController.getString(popupOptions[Utilities.clamp(option, popupOptions.length - 1, 0)]); + return getString(popupOptions[Utilities.clamp(option, popupOptions.length - 1, 0)]); } private String getSound() { final SharedPreferences prefs = getNotificationsSettings(); - String value = LocaleController.getString("SoundDefault", R.string.SoundDefault); + String value = getString("SoundDefault", R.string.SoundDefault); long documentId; switch (currentType) { case TYPE_PRIVATE: @@ -293,6 +307,11 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements value = prefs.getString("GroupSound", value); documentId = prefs.getLong("GroupSoundDocId", 0); break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: + value = prefs.getString("ReactionSound", value); + documentId = prefs.getLong("ReactionSoundDocId", 0); + break; case TYPE_STORIES: value = prefs.getString("StoriesSound", value); documentId = prefs.getLong("StoriesSoundDocId", 0); @@ -305,14 +324,14 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (documentId != 0) { TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId); if (document == null) { - return LocaleController.getString("CustomSound", R.string.CustomSound); + return getString("CustomSound", R.string.CustomSound); } else { return NotificationsSoundActivity.trimTitle(document, FileLoader.getDocumentFileName(document)); } } else if (value.equals("NoSound")) { - return LocaleController.getString("NoSound", R.string.NoSound); + return getString("NoSound", R.string.NoSound); } else if (value.equals("Default")) { - return LocaleController.getString("SoundDefault", R.string.SoundDefault); + return getString("SoundDefault", R.string.SoundDefault); } return value; } @@ -324,8 +343,10 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements case TYPE_GROUP: option = getNotificationsSettings().getInt("priority_group", 1); break; case TYPE_STORIES: option = getNotificationsSettings().getInt("priority_stories", 1); break; case TYPE_CHANNEL: option = getNotificationsSettings().getInt("priority_channel", 1); break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: option = getNotificationsSettings().getInt("priority_react", 1); break; } - return LocaleController.getString(priorityOptions[Utilities.clamp(option, priorityOptions.length - 1, 0)]); + return getString(priorityOptions[Utilities.clamp(option, priorityOptions.length - 1, 0)]); } @Override @@ -336,9 +357,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (currentType == -1) { - actionBar.setTitle(LocaleController.getString("NotificationsExceptions", R.string.NotificationsExceptions)); + actionBar.setTitle(getString("NotificationsExceptions", R.string.NotificationsExceptions)); } else { - actionBar.setTitle(LocaleController.getString("Notifications", R.string.Notifications)); + actionBar.setTitle(getString("Notifications", R.string.Notifications)); } actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -362,7 +383,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements searchAdapter.searchDialogs(null); searching = false; searchWas = false; - emptyView.setText(LocaleController.getString("NoExceptions", R.string.NoExceptions)); + emptyView.setText(getString("NoExceptions", R.string.NoExceptions)); listView.setAdapter(adapter); adapter.notifyDataSetChanged(); listView.setFastScrollVisible(true); @@ -379,7 +400,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (text.length() != 0) { searchWas = true; if (listView != null) { - emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + emptyView.setText(getString("NoResult", R.string.NoResult)); emptyView.showProgress(); listView.setAdapter(searchAdapter); searchAdapter.notifyDataSetChanged(); @@ -390,7 +411,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements searchAdapter.searchDialogs(text); } }); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(getString("Search", R.string.Search)); } searchAdapter = new SearchAdapter(context); @@ -401,7 +422,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements emptyView = new EmptyTextProgressView(context); emptyView.setTextSize(18); - emptyView.setText(LocaleController.getString("NoExceptions", R.string.NoExceptions)); + emptyView.setText(getString("NoExceptions", R.string.NoExceptions)); emptyView.showTextView(); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -409,12 +430,17 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements @Override protected void dispatchDraw(Canvas canvas) { if (currentType != -1) { - drawSectionBackground(canvas, exceptionsStart, exceptionsEnd, getThemedColor(Theme.key_windowBackgroundWhite)); + if (exceptionsStart >= 0) { + drawSectionBackground(canvas, exceptionsStart, exceptionsEnd, getThemedColor(Theme.key_windowBackgroundWhite)); + } + if (currentType != TYPE_REACTIONS_MESSAGES && currentType != TYPE_REACTIONS_STORIES) { + drawSectionBackground(canvas, settingsStart, settingsEnd, getThemedColor(Theme.key_windowBackgroundWhite)); + } } super.dispatchDraw(canvas); } }; - listView.setTranslateSelector(true); +// listView.setTranslateSelector(true); listView.setEmptyView(emptyView); listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setVerticalScrollBarEnabled(false); @@ -429,16 +455,22 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (listView.getAdapter() == adapter && position >= 0 && position < items.size()) { item = items.get(position); } + if (item != null && item.viewType == VIEW_TYPE_EXPAND) { + expanded = !expanded; + updateRows(true); + return; + } if (currentType == TYPE_STORIES && item != null && item.exception != null) { NotificationsSettingsActivity.NotificationException exception = item.exception; ItemOptions.makeOptions(NotificationsCustomSettingsActivity.this, view) - .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, LocaleController.getString(R.string.NotificationsStoryMute), false, () -> { + .setGravity(Gravity.LEFT) + .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, getString(R.string.NotificationsStoryMute), false, () -> { updateMute(exception, view, position, false, true); }) - .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, LocaleController.getString(R.string.NotificationsStoryUnmute), false, () -> { + .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, getString(R.string.NotificationsStoryUnmute), false, () -> { updateMute(exception, view, position, false, false); }) - .addIf(!exception.auto, R.drawable.msg_delete, LocaleController.getString("DeleteException", R.string.DeleteException), true, () -> { + .addIf(!exception.auto, R.drawable.msg_delete, getString("DeleteException", R.string.DeleteException), true, () -> { deleteException(exception, view, position); }) .show(); @@ -482,15 +514,16 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements } ItemOptions.makeOptions(NotificationsCustomSettingsActivity.this, view) - .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, LocaleController.getString(R.string.NotificationsStoryMute), false, () -> { + .setGravity(Gravity.LEFT) + .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, getString(R.string.NotificationsStoryMute), false, () -> { actionBar.closeSearchField(); updateMute(exception, view, -1, newException, true); }) - .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, LocaleController.getString(R.string.NotificationsStoryUnmute), false, () -> { + .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, getString(R.string.NotificationsStoryUnmute), false, () -> { actionBar.closeSearchField(); updateMute(exception, view, -1, newException, false); }) - .addIf(!newException && !exception.auto, R.drawable.msg_delete, LocaleController.getString("DeleteException", R.string.DeleteException), true, () -> { + .addIf(!newException && !exception.auto, R.drawable.msg_delete, getString("DeleteException", R.string.DeleteException), true, () -> { deleteException(exception, view, position); }) .show(); @@ -545,7 +578,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements } long did = exception.did; - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did, false, false); ChatNotificationsPopupWrapper chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, null, true, true, new ChatNotificationsPopupWrapper.Callback() { @Override public void toggleSound() { @@ -719,9 +752,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements presentFragment(activity); } else if (item.id == 7) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("NotificationsDeleteAllExceptionTitle", R.string.NotificationsDeleteAllExceptionTitle)); - builder.setMessage(LocaleController.getString("NotificationsDeleteAllExceptionAlert", R.string.NotificationsDeleteAllExceptionAlert)); - builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> { + builder.setTitle(getString("NotificationsDeleteAllExceptionTitle", R.string.NotificationsDeleteAllExceptionTitle)); + builder.setMessage(getString("NotificationsDeleteAllExceptionAlert", R.string.NotificationsDeleteAllExceptionAlert)); + builder.setPositiveButton(getString("Delete", R.string.Delete), (dialogInterface, i) -> { SharedPreferences preferences = getNotificationsSettings(); SharedPreferences.Editor editor = preferences.edit(); for (int a = 0, N = exceptions.size(); a < N; a++) { @@ -748,16 +781,16 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements updateRows(true); getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); AlertDialog alertDialog = builder.create(); showDialog(alertDialog); TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); } - } else if (item.viewType == VIEW_TYPE_CHECK2) { + } else if (item.id == BUTTON_ENABLE || item.id == BUTTON_NEW_STORIES) { enabled = getNotificationsController().isGlobalNotificationsEnabled(currentType); - NotificationsCheckCell checkCell = (NotificationsCheckCell) view; + TextCheckCell checkCell = (TextCheckCell) view; RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(position); if (currentType == TYPE_STORIES) { @@ -771,24 +804,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements editor.putBoolean("EnableAllStories", !enabled); storiesEnabled = !enabled; } - editor.commit(); + editor.apply(); getNotificationsController().updateServerNotificationsSettings(currentType); - checkCell.setChecked(!enabled); - if (holder != null) { - adapter.onBindViewHolder(holder, position); - } - for (int i = 0; i < items.size(); ++i) { - ItemInner item2 = items.get(i); - if (item2.id == 5) { - item2.checked = storiesAuto && (storiesEnabled == null || !storiesEnabled); - RecyclerView.ViewHolder holder2 = listView.findViewHolderForAdapterPosition(i); - if (holder2 != null && holder2.itemView instanceof TextCheckCell) { - TextCheckCell checkCell1 = (TextCheckCell) holder2.itemView; - checkCell1.setChecked(item2.checked); - } - break; - } - } + updateRows(true); if (showAutoExceptions != (storiesEnabled == null)) { toggleShowAutoExceptions(); } @@ -798,36 +816,10 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (!enabled) { getNotificationsController().setGlobalNotificationsEnabled(currentType, 0); - checkCell.setChecked(true); - if (holder != null) { - adapter.onBindViewHolder(holder, position); - } - checkRowsEnabled(); + updateRows(true); } else { AlertsCreator.showCustomNotificationsDialog(NotificationsCustomSettingsActivity.this, 0, 0, currentType, exceptions, autoExceptions, currentAccount, param -> { - int offUntil; - SharedPreferences preferences = getNotificationsSettings(); - if (currentType == TYPE_PRIVATE) { - offUntil = preferences.getInt("EnableAll2", 0); - } else if (currentType == TYPE_GROUP) { - offUntil = preferences.getInt("EnableGroup2", 0); - } else { - offUntil = preferences.getInt("EnableChannel2", 0); - } - int currentTime = getConnectionsManager().getCurrentTime(); - int iconType; - if (offUntil < currentTime) { - iconType = 0; - } else if (offUntil - 60 * 60 * 24 * 365 >= currentTime) { - iconType = 0; - } else { - iconType = 2; - } - checkCell.setChecked(getNotificationsController().isGlobalNotificationsEnabled(currentType), iconType); - if (holder != null) { - adapter.onBindViewHolder(holder, position); - } - checkRowsEnabled(); + updateRows(true); }); } } else if (item.id == 3) { @@ -850,7 +842,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (position >= 0 && position < items.size()) { items.get(position).color = getLedColor(); } - ((TextColorCell) view).setTextAndColor(LocaleController.getString("LedColor", R.string.LedColor), getLedColor(), true); + ((TextColorCell) view).setTextAndColor(getString("LedColor", R.string.LedColor), getLedColor(), true); } else { updateRows(true); } @@ -864,7 +856,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (position >= 0 && position < items.size()) { items.get(position).text2 = getPopupOption(); } - ((TextSettingsCell) view).setTextAndValue(LocaleController.getString("PopupNotification", R.string.PopupNotification), getPopupOption(), true, ((TextSettingsCell) view).needDivider); + ((TextSettingsCell) view).setTextAndValue(getString("PopupNotification", R.string.PopupNotification), getPopupOption(), true, ((TextSettingsCell) view).needDivider); } else { updateRows(true); } @@ -880,16 +872,18 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements key = "vibrate_group"; } else if (currentType == TYPE_STORIES) { key = "vibrate_stories"; + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + key = "vibrate_react"; } else { key = "vibrate_channel"; } showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), 0, 0, key, () -> { if (view instanceof TextSettingsCell) { - String value = LocaleController.getString(vibrateLabels[Utilities.clamp(getNotificationsSettings().getInt(key, 0), vibrateLabels.length - 1, 0)]); + String value = getString(vibrateLabels[Utilities.clamp(getNotificationsSettings().getInt(key, 0), vibrateLabels.length - 1, 0)]); if (position >= 0 && position < items.size()) { items.get(position).text2 = value; } - ((TextSettingsCell) view).setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), value, true, true); + ((TextSettingsCell) view).setTextAndValue(getString("Vibrate", R.string.Vibrate), value, true, true); } else { updateRows(true); } @@ -903,12 +897,12 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (position >= 0 && position < items.size()) { items.get(position).text2 = getPriorityOption(); } - ((TextSettingsCell) view).setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption(), true, ((TextSettingsCell) view).needDivider); + ((TextSettingsCell) view).setTextAndValue(getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption(), true, ((TextSettingsCell) view).needDivider); } else { updateRows(true); } })); - } else if (item.id == 5) { + } else if (item.id == BUTTON_IMPORTANT_STORIES) { if (!view.isEnabled()) { return; } @@ -950,6 +944,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements } else if (currentType == TYPE_STORIES) { enabled = !preferences.getBoolean("EnableHideStoriesSenders", false); editor.putBoolean("EnableHideStoriesSenders", enabled); + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + enabled = preferences.getBoolean("EnableReactionsPreview", true); + editor.putBoolean("EnableReactionsPreview", !enabled); } else { enabled = preferences.getBoolean("EnablePreviewChannel", true); editor.putBoolean("EnablePreviewChannel", !enabled); @@ -959,6 +956,56 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!enabled); } + } else if (item != null && (item.id == BUTTON_MESSAGES_REACTIONS || item.id == BUTTON_STORIES_REACTIONS)) { + final boolean check = LocaleController.isRTL ? x < dp(76) : x > view.getMeasuredWidth() - dp(76); + + SharedPreferences prefs = getNotificationsSettings(); + if (check) { + final String key = item.id == BUTTON_MESSAGES_REACTIONS ? "EnableReactionsMessages" : "EnableReactionsStories"; + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(key, !prefs.getBoolean(key, true)); + editor.apply(); + updateRows(true); + getNotificationsController().updateServerNotificationsSettings(currentType); + } else { + final String key = item.id == BUTTON_MESSAGES_REACTIONS ? "EnableReactionsMessagesContacts" : "EnableReactionsStoriesContacts"; + final LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + boolean[] contacts = new boolean[] { prefs.getBoolean(key, false) }; + + RadioColorCell[] cells = new RadioColorCell[2]; + for (int a = 0; a < cells.length; ++a) { + cells[a] = new RadioColorCell(context, getResourceProvider()); + cells[a].setPadding(dp(4), 0, dp(4), 0); + cells[a].setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); + cells[a].setTextAndValue(getString(a == 0 ? R.string.NotifyAboutReactionsFromEveryone : R.string.NotifyAboutReactionsFromContacts), a == 0 ? !contacts[0] : contacts[0]); + cells[a].setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); + linearLayout.addView(cells[a]); + final int finalA = a; + cells[a].setOnClickListener(v -> { + contacts[0] = finalA == 1; + for (int i = 0; i < cells.length; ++i) { + cells[i].setChecked(contacts[0] == (i == 1), true); + } + }); + } + + showDialog( + new AlertDialog.Builder(getContext(), resourceProvider) + .setTitle(getString(R.string.NotifyAboutReactionsFrom)) + .setView(linearLayout) + .setNegativeButton(getString(R.string.Cancel), null) + .setPositiveButton(getString(R.string.Save), (di, w) -> { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(key, contacts[0]); + editor.apply(); + updateRows(true); + getNotificationsController().updateServerNotificationsSettings(currentType); + }) + .create() + ); + } } }); DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { @@ -1015,8 +1062,8 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements item = items.get(position); } final boolean enabled; - if (item != null && item.id == 5) { - enabled = storiesEnabled == null || !storiesEnabled; + if (item != null && (item.id == BUTTON_IMPORTANT_STORIES || item.id == BUTTON_NEW_STORIES || item.id == BUTTON_ENABLE)) { + enabled = true; } else { enabled = globalEnabled; } @@ -1296,6 +1343,14 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements R.string.NotificationsPriorityMedium }; + private static final int BUTTON_ENABLE = 100; + private static final int BUTTON_NEW_STORIES = 101; + private static final int BUTTON_IMPORTANT_STORIES = 102; + private static final int BUTTON_MESSAGES_REACTIONS = 103; + private static final int BUTTON_STORIES_REACTIONS = 104; + + boolean expanded; + private void updateRows(boolean animated) { oldItems.clear(); oldItems.addAll(items); @@ -1303,68 +1358,137 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements SharedPreferences prefs = getNotificationsSettings(); boolean enabled = false; if (currentType != -1) { - items.add(ItemInner.asCheck2()); - items.add(ItemInner.asShadow(null)); - items.add(ItemInner.asHeader(LocaleController.getString(R.string.SETTINGS))); + items.add(ItemInner.asHeader(getString(R.string.NotifyMeAbout))); + if (currentType == TYPE_STORIES) { + items.add(ItemInner.asCheck(BUTTON_NEW_STORIES, getString(R.string.NotifyMeAboutNewStories), prefs.getBoolean("EnableAllStories", false))); + if (!prefs.getBoolean("EnableAllStories", false)) { + items.add(ItemInner.asCheck(BUTTON_IMPORTANT_STORIES, getString(R.string.NotifyMeAboutImportantStories), storiesAuto && (storiesEnabled == null || !storiesEnabled))); + } + items.add(ItemInner.asShadow(-1, getString(R.string.StoryAutoExceptionsInfo))); + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + items.add(ItemInner.asCheck2( + BUTTON_MESSAGES_REACTIONS, + R.drawable.msg_markunread, + getString(R.string.NotifyMeAboutMessagesReactions), + getString( + !prefs.getBoolean("EnableReactionsMessages", true) ? + R.string.NotifyFromNobody : + prefs.getBoolean("EnableReactionsMessagesContacts", false) ? + R.string.NotifyFromContacts : + R.string.NotifyFromEveryone + ), + prefs.getBoolean("EnableReactionsMessages", true) + )); + items.add(ItemInner.asCheck2( + BUTTON_STORIES_REACTIONS, + R.drawable.msg_stories_saved, + getString(R.string.NotifyMeAboutStoriesReactions), + getString( + !prefs.getBoolean("EnableReactionsStories", true) ? + R.string.NotifyFromNobody : + prefs.getBoolean("EnableReactionsStoriesContacts", false) ? + R.string.NotifyFromContacts : + R.string.NotifyFromEveryone + ), + prefs.getBoolean("EnableReactionsStories", true) + )); + items.add(ItemInner.asShadow(-1, null)); + } else { + int text; + if (currentType == TYPE_PRIVATE) { + text = R.string.NotifyMeAboutPrivate; + } else if (currentType == TYPE_GROUP) { + text = R.string.NotifyMeAboutGroups; + } else { + text = R.string.NotifyMeAboutChannels; + } + items.add(ItemInner.asCheck(BUTTON_ENABLE, getString(text), getNotificationsController().isGlobalNotificationsEnabled(currentType))); + items.add(ItemInner.asShadow(-1, null)); + } + items.add(ItemInner.asHeader(getString(R.string.SETTINGS))); + settingsStart = items.size() - 1; if (currentType == TYPE_STORIES) { - items.add(ItemInner.asCheck(0, LocaleController.getString(R.string.NotificationShowSenderNames), !prefs.getBoolean("EnableHideStoriesSenders", false))); + items.add(ItemInner.asCheck(0, getString(R.string.NotificationShowSenderNames), !prefs.getBoolean("EnableHideStoriesSenders", false))); + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + items.add(ItemInner.asCheck(0, getString(R.string.NotificationShowSenderNames), prefs.getBoolean("EnableReactionsPreview", true))); } else { switch (currentType) { case TYPE_PRIVATE: enabled = prefs.getBoolean("EnablePreviewAll", true); break; case TYPE_GROUP: enabled = prefs.getBoolean("EnablePreviewGroup", true); break; case TYPE_CHANNEL: enabled = prefs.getBoolean("EnablePreviewChannel", true); break; } - items.add(ItemInner.asCheck(0, LocaleController.getString(R.string.MessagePreview), enabled)); + items.add(ItemInner.asCheck(0, getString(R.string.MessagePreview), enabled)); } - items.add(ItemInner.asColor(LocaleController.getString("LedColor", R.string.LedColor), getLedColor())); + items.add(ItemInner.asSetting(3, getString("Sound", R.string.Sound), getSound())); - int vibrate = 0; - switch (currentType) { - case TYPE_PRIVATE: vibrate = prefs.getInt("vibrate_messages", 0); break; - case TYPE_GROUP: vibrate = prefs.getInt("vibrate_group", 0); break; - case TYPE_STORIES: vibrate = prefs.getInt("vibrate_stories", 0); break; - case TYPE_CHANNEL: vibrate = prefs.getInt("vibrate_channel", 0); break; - } - items.add(ItemInner.asSetting(1, LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString(vibrateLabels[Utilities.clamp(vibrate, vibrateLabels.length - 1, 0)]))); + if (expanded) { - if (currentType == TYPE_PRIVATE || currentType == TYPE_GROUP) { - items.add(ItemInner.asSetting(2, LocaleController.getString("PopupNotification", R.string.PopupNotification), getPopupOption())); - } + items.add(ItemInner.asColor(getString("LedColor", R.string.LedColor), getLedColor())); - items.add(ItemInner.asSetting(3, LocaleController.getString("Sound", R.string.Sound), getSound())); + int vibrate = 0; + switch (currentType) { + case TYPE_PRIVATE: + vibrate = prefs.getInt("vibrate_messages", 0); + break; + case TYPE_GROUP: + vibrate = prefs.getInt("vibrate_group", 0); + break; + case TYPE_STORIES: + vibrate = prefs.getInt("vibrate_stories", 0); + break; + case TYPE_CHANNEL: + vibrate = prefs.getInt("vibrate_channel", 0); + break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: + vibrate = prefs.getInt("vibrate_react", 0); + break; + } + items.add(ItemInner.asSetting(1, getString("Vibrate", R.string.Vibrate), getString(vibrateLabels[Utilities.clamp(vibrate, vibrateLabels.length - 1, 0)]))); - if (Build.VERSION.SDK_INT >= 21) { - items.add(ItemInner.asSetting(4, LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption())); - } + if (currentType == TYPE_PRIVATE || currentType == TYPE_GROUP) { + items.add(ItemInner.asSetting(2, getString("PopupNotification", R.string.PopupNotification), getPopupOption())); + } - if (currentType == TYPE_STORIES) { - items.add(ItemInner.asCheck(5, LocaleController.getString(R.string.StoryAutoExceptions), storiesAuto && (storiesEnabled == null || !storiesEnabled))); - items.add(ItemInner.asShadow(LocaleController.getString(R.string.StoryAutoExceptionsInfo))); + if (Build.VERSION.SDK_INT >= 21) { + items.add(ItemInner.asSetting(4, getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption())); + } + + items.add(ItemInner.asExpand(getString(R.string.NotifyLessOptions), false)); } else { - items.add(ItemInner.asShadow(null)); + items.add(ItemInner.asExpand(getString(R.string.NotifyMoreOptions), true)); } + settingsEnd = items.size() - 1; - items.add(ItemInner.asButton(6, R.drawable.msg_contact_add, LocaleController.getString("NotificationsAddAnException", R.string.NotificationsAddAnException))); + items.add(ItemInner.asShadow(-2, null)); } - exceptionsStart = items.size() - 1; - if (autoExceptions != null && showAutoExceptions) { - for (int i = 0; i < autoExceptions.size(); ++i) { - items.add(ItemInner.asException(autoExceptions.get(i))); + if (currentType != TYPE_REACTIONS_MESSAGES && currentType != TYPE_REACTIONS_STORIES) { + if (currentType != -1) { + items.add(ItemInner.asButton(6, R.drawable.msg_contact_add, getString("NotificationsAddAnException", R.string.NotificationsAddAnException))); } - } - if (exceptions != null) { - for (int i = 0; i < exceptions.size(); ++i) { - items.add(ItemInner.asException(exceptions.get(i))); + exceptionsStart = items.size() - 1; + if (autoExceptions != null && showAutoExceptions) { + for (int i = 0; i < autoExceptions.size(); ++i) { + items.add(ItemInner.asException(autoExceptions.get(i))); + } } - } - exceptionsEnd = items.size() - 1; - if (currentType != -1 || exceptions != null && !exceptions.isEmpty()) { - items.add(ItemInner.asShadow(null)); - } - if (exceptions != null && !exceptions.isEmpty()) { - items.add(ItemInner.asButton(7, 0, LocaleController.getString("NotificationsDeleteAllException", R.string.NotificationsDeleteAllException))); + if (exceptions != null) { + for (int i = 0; i < exceptions.size(); ++i) { + items.add(ItemInner.asException(exceptions.get(i))); + } + } + exceptionsEnd = items.size() - 1; + if (currentType != -1 || exceptions != null && !exceptions.isEmpty()) { + items.add(ItemInner.asShadow(-3, null)); + } + if (exceptions != null && !exceptions.isEmpty()) { + items.add(ItemInner.asButton(7, 0, getString("NotificationsDeleteAllException", R.string.NotificationsDeleteAllException))); + } + } else { + exceptionsStart = -1; + exceptionsEnd = -1; } if (adapter != null) { if (animated) { @@ -1390,7 +1514,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements Ringtone rng = RingtoneManager.getRingtone(getParentActivity(), ringtone); if (rng != null) { if (ringtone.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) { - name = LocaleController.getString("SoundDefault", R.string.SoundDefault); + name = getString("SoundDefault", R.string.SoundDefault); } else { name = rng.getTitle(getParentActivity()); } @@ -1676,14 +1800,14 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements position -= searchResult.size() + 1; ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); TLObject object = globalSearch.get(position); - cell.setData(object, null, LocaleController.getString("NotificationsOn", R.string.NotificationsOn), 0, position != globalSearch.size() - 1); + cell.setData(object, null, getString("NotificationsOn", R.string.NotificationsOn), 0, position != globalSearch.size() - 1); cell.setAddButtonVisible(true); } break; } case 1: { GraySectionCell cell = (GraySectionCell) holder.itemView; - cell.setText(LocaleController.getString("AddToExceptions", R.string.AddToExceptions)); + cell.setText(getString("AddToExceptions", R.string.AddToExceptions)); break; } } @@ -1706,6 +1830,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements private static final int VIEW_TYPE_SETTING = 5; private static final int VIEW_TYPE_CHECK2 = 6; private static final int VIEW_TYPE_BUTTON = 7; + private static final int VIEW_TYPE_EXPAND = 8; private static class ItemInner extends AdapterWithDiffUtils.Item { @@ -1732,6 +1857,15 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements item.checked = checked; return item; } + public static ItemInner asCheck2(int id, int icon, CharSequence text, CharSequence subtext, boolean checked) { + ItemInner item = new ItemInner(VIEW_TYPE_CHECK2); + item.id = id; + item.resId = icon; + item.text = text; + item.text2 = subtext; + item.checked = checked; + return item; + } public static ItemInner asException(NotificationsSettingsActivity.NotificationException exception) { ItemInner item = new ItemInner(VIEW_TYPE_USER); item.exception = exception; @@ -1743,8 +1877,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements item.color = color; return item; } - public static ItemInner asShadow(CharSequence text) { + public static ItemInner asShadow(int id, CharSequence text) { ItemInner item = new ItemInner(VIEW_TYPE_SHADOW); + item.id = id; item.text = text; return item; } @@ -1755,9 +1890,6 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements item.text2 = value; return item; } - public static ItemInner asCheck2() { - return new ItemInner(VIEW_TYPE_CHECK2); - } public static ItemInner asButton(int id, int resId, CharSequence text) { ItemInner item = new ItemInner(VIEW_TYPE_BUTTON); item.id = id; @@ -1765,9 +1897,23 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements item.text = text; return item; } + public static ItemInner asExpand(CharSequence text, boolean expand) { + ItemInner item = new ItemInner(VIEW_TYPE_EXPAND); + item.text = text; + item.resId = expand ? 1 : 0; + return item; + } @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ItemInner itemInner = (ItemInner) o; + return id == itemInner.id && color == itemInner.color && (viewType == VIEW_TYPE_EXPAND || resId == itemInner.resId && Objects.equals(text, itemInner.text) && (viewType == VIEW_TYPE_CHECK2 || Objects.equals(text2, itemInner.text2))) && exception == itemInner.exception; + } + + @Override + protected boolean contentsEquals(AdapterWithDiffUtils.Item o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ItemInner itemInner = (ItemInner) o; @@ -1825,7 +1971,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case VIEW_TYPE_CHECK2: - view = new NotificationsCheckCell(mContext); + view = new NotificationsCheckCell(mContext, 21, 64, true, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case VIEW_TYPE_BUTTON: @@ -1833,6 +1979,10 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements view = new TextCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case VIEW_TYPE_EXPAND: + view = new ExpandView(mContext); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; } return new RecyclerListView.Holder(view); } @@ -1888,39 +2038,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements } case VIEW_TYPE_CHECK2: { NotificationsCheckCell checkCell = (NotificationsCheckCell) holder.itemView; - checkCell.setDrawLine(false); - String text; - StringBuilder builder = new StringBuilder(); - int offUntil; - SharedPreferences preferences = getNotificationsSettings(); - - if (currentType == TYPE_PRIVATE) { - text = LocaleController.getString("NotificationsForPrivateChats", R.string.NotificationsForPrivateChats); - offUntil = preferences.getInt("EnableAll2", 0); - } else if (currentType == TYPE_GROUP) { - text = LocaleController.getString("NotificationsForGroups", R.string.NotificationsForGroups); - offUntil = preferences.getInt("EnableGroup2", 0); - } else if (currentType == TYPE_STORIES) { - text = LocaleController.getString("NotificationsForStories", R.string.NotificationsForStories); - offUntil = preferences.getBoolean("EnableAllStories", false) ? 0 : Integer.MAX_VALUE; - } else { - text = LocaleController.getString("NotificationsForChannels", R.string.NotificationsForChannels); - offUntil = preferences.getInt("EnableChannel2", 0); - } - int currentTime = getConnectionsManager().getCurrentTime(); - boolean enabled; - int iconType; - if (enabled = offUntil < currentTime) { - builder.append(LocaleController.getString("NotificationsOn", R.string.NotificationsOn)); - iconType = 0; - } else if (offUntil - 60 * 60 * 24 * 365 >= currentTime) { - builder.append(LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); - iconType = 0; - } else { - builder.append(LocaleController.formatString("NotificationsOffUntil", R.string.NotificationsOffUntil, LocaleController.stringForMessageListDate(offUntil))); - iconType = 2; - } - checkCell.setTextAndValueAndCheck(text, builder, enabled, iconType, false); + checkCell.setDrawLine(true); + checkCell.setChecked(item.checked); + checkCell.setTextAndValueAndIconAndCheck(item.text, item.text2, item.resId, item.checked, 0, false, divider, true); break; } case VIEW_TYPE_BUTTON: { @@ -1934,6 +2054,12 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements } break; } + case VIEW_TYPE_EXPAND: { + ExpandView textCell = (ExpandView) holder.itemView; + textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); + textCell.set(item.text, item.resId == 1, divider); + break; + } } } @@ -1954,8 +2080,9 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements item = items.get(position); } final boolean enabled; - if (item != null && item.id == 5) { - enabled = storiesEnabled == null || !storiesEnabled; + if (item != null && item.id == BUTTON_IMPORTANT_STORIES) { + return; +// enabled = storiesEnabled == null || !storiesEnabled; } else { enabled = globalEnabled; } @@ -1992,6 +2119,49 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements } } + public class ExpandView extends TextCell { + public ImageView imageView; + public ExpandView(Context context) { + super(context); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN)); + imageView.setImageResource(R.drawable.msg_expand); + addView(imageView, LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 17, 0, 17,0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + imageView.measure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int w = right - left; + int l = LocaleController.isRTL ? dp(17) : w - dp(17 + 24); + int t = (bottom - top - dp(24)) / 2; + imageView.layout(l, t, l + dp(24), t + dp(24)); + } + + public void set(CharSequence text, boolean expand, boolean divider) { + setArrow(expand, true); + setText(text, divider); + } + + public void setArrow(boolean expand, boolean animated) { + if (animated) { + imageView.animate().rotation(expand ? 0 : 180).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(340).start(); + } else { + imageView.setRotation(expand ? 0 : 180); + } + } + + } + @Override public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 3e8edffb5..574977517 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.LocaleController.getString; + import android.app.Activity; import android.content.Context; import android.content.DialogInterface; @@ -102,6 +104,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif private int groupRow; private int channelsRow; private int storiesRow; + private int reactionsRow; private int notificationsSection2Row; private int inappSectionRow; @@ -157,6 +160,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif groupRow = rowCount++; channelsRow = rowCount++; storiesRow = rowCount++; + reactionsRow = rowCount++; notificationsSection2Row = rowCount++; callsSectionRow = rowCount++; @@ -199,6 +203,8 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.notificationsSettingsUpdated); + getMessagesController().reloadReactionsNotifySettings(); + return super.onFragmentCreate(); } @@ -422,7 +428,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); - actionBar.setTitle(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); + actionBar.setTitle(getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { @@ -453,7 +459,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif if (getParentActivity() == null) { return; } - if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow) { + if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow || position == reactionsRow) { int type; ArrayList exceptions; ArrayList autoExceptions = null; @@ -470,12 +476,16 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif exceptions = exceptionStories; autoExceptions = exceptionAutoStories; enabled = getNotificationsSettings().getBoolean("EnableAllStories", false); + } else if (position == reactionsRow) { + type = NotificationsController.TYPE_REACTIONS_MESSAGES; + exceptions = null; + enabled = getNotificationsSettings().getBoolean("EnableReactionsMessages", true) || getNotificationsSettings().getBoolean("EnableReactionsStories", true); } else { type = NotificationsController.TYPE_CHANNEL; exceptions = exceptionChannels; enabled = getNotificationsController().isGlobalNotificationsEnabled(type); } - if (exceptions == null) { + if (exceptions == null && type != NotificationsController.TYPE_REACTIONS_MESSAGES) { return; } @@ -492,6 +502,21 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } edit.apply(); getNotificationsController().updateServerNotificationsSettings(type); + } else if ( + type == NotificationsController.TYPE_REACTIONS_MESSAGES || + type == NotificationsController.TYPE_REACTIONS_STORIES + ) { + SharedPreferences.Editor edit = getNotificationsSettings().edit(); + if (enabledFinal) { + edit.putBoolean("EnableReactionsMessages", false); + edit.putBoolean("EnableReactionsStories", false); + } else { + edit.putBoolean("EnableReactionsMessages", true); + edit.putBoolean("EnableReactionsStories", true); + } + edit.apply(); + getNotificationsController().updateServerNotificationsSettings(type); + getNotificationsController().deleteNotificationChannelGlobal(type); } else { getNotificationsController().setGlobalNotificationsEnabled(type, !enabledFinal ? 0 : Integer.MAX_VALUE); } @@ -531,9 +556,9 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } } else if (position == resetNotificationsRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("ResetNotificationsAlertTitle", R.string.ResetNotificationsAlertTitle)); - builder.setMessage(LocaleController.getString("ResetNotificationsAlert", R.string.ResetNotificationsAlert)); - builder.setPositiveButton(LocaleController.getString("Reset", R.string.Reset), (dialogInterface, i) -> { + builder.setTitle(getString("ResetNotificationsAlertTitle", R.string.ResetNotificationsAlertTitle)); + builder.setMessage(getString("ResetNotificationsAlert", R.string.ResetNotificationsAlert)); + builder.setPositiveButton(getString("Reset", R.string.Reset), (dialogInterface, i) -> { if (reseting) { return; } @@ -550,13 +575,13 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif exceptionUsers.clear(); adapter.notifyDataSetChanged(); if (getParentActivity() != null) { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("ResetNotificationsText", R.string.ResetNotificationsText), Toast.LENGTH_SHORT); + Toast toast = Toast.makeText(getParentActivity(), getString("ResetNotificationsText", R.string.ResetNotificationsText), Toast.LENGTH_SHORT); toast.show(); } getMessagesStorage().updateMutedDialogsFiltersCounters(); })); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); AlertDialog alertDialog = builder.create(); showDialog(alertDialog); TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); @@ -700,9 +725,9 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif })); } else if (position == repeatRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications)); + builder.setTitle(getString("RepeatNotifications", R.string.RepeatNotifications)); builder.setItems(new CharSequence[]{ - LocaleController.getString("RepeatDisabled", R.string.RepeatDisabled), + getString("RepeatDisabled", R.string.RepeatDisabled), LocaleController.formatPluralString("Minutes", 5), LocaleController.formatPluralString("Minutes", 10), LocaleController.formatPluralString("Minutes", 30), @@ -729,7 +754,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif updateRepeatNotifications = true; adapter.notifyItemChanged(position); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } if (view instanceof TextCheckCell) { @@ -750,13 +775,13 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif if (rng != null) { if (requestCode == callsRingtoneRow) { if (ringtone.equals(Settings.System.DEFAULT_RINGTONE_URI)) { - name = LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone); + name = getString("DefaultRingtone", R.string.DefaultRingtone); } else { name = rng.getTitle(getParentActivity()); } } else { if (ringtone.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) { - name = LocaleController.getString("SoundDefault", R.string.SoundDefault); + name = getString("SoundDefault", R.string.SoundDefault); } else { name = rng.getTitle(getParentActivity()); } @@ -806,6 +831,9 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif if (exceptions != null && !exceptions.isEmpty()) { alertText = LocaleController.formatPluralString("Groups", exceptions.size()); } + } else if (position == reactionsRow) { + whenDone.run(); + return; } else { exceptions = exceptionChannels; autoExceptions = null; @@ -823,9 +851,9 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } else { builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsExceptionsAlert", R.string.NotificationsExceptionsAlert, alertText))); } - builder.setTitle(LocaleController.getString("NotificationsExceptions", R.string.NotificationsExceptions)); - builder.setNeutralButton(LocaleController.getString("ViewExceptions", R.string.ViewExceptions), (dialogInterface, i) -> presentFragment(new NotificationsCustomSettingsActivity(-1, exceptions, autoExceptions))); - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), (di, i) -> whenDone.run()); + builder.setTitle(getString("NotificationsExceptions", R.string.NotificationsExceptions)); + builder.setNeutralButton(getString("ViewExceptions", R.string.ViewExceptions), (dialogInterface, i) -> presentFragment(new NotificationsCustomSettingsActivity(-1, exceptions, autoExceptions))); + builder.setNegativeButton(getString("OK", R.string.OK), (di, i) -> whenDone.run()); showDialog(builder.create()); } @@ -873,11 +901,11 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif View view; switch (viewType) { case 0: - view = new HeaderCell(mContext); + view = new HeaderCell(mContext, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 1: - view = new TextCheckCell(mContext); + view = new TextCheckCell(mContext, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 2: @@ -885,19 +913,19 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 3: - view = new NotificationsCheckCell(mContext); + view = new NotificationsCheckCell(mContext, 21, 64, true, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 4: - view = new ShadowSectionCell(mContext); + view = new ShadowSectionCell(mContext, resourceProvider); break; case 5: - view = new TextSettingsCell(mContext); + view = new TextSettingsCell(mContext, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 6: default: - view = new TextInfoPrivacyCell(mContext); + view = new TextInfoPrivacyCell(mContext, resourceProvider); view.setBackgroundDrawable(Theme.getThemedDrawableByKey(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); break; } @@ -910,21 +938,21 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif case 0: { HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == notificationsSectionRow) { - headerCell.setText(LocaleController.getString("NotificationsForChats", R.string.NotificationsForChats)); + headerCell.setText(getString("NotificationsForChats", R.string.NotificationsForChats)); } else if (position == inappSectionRow) { - headerCell.setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications)); + headerCell.setText(getString("InAppNotifications", R.string.InAppNotifications)); } else if (position == eventsSectionRow) { - headerCell.setText(LocaleController.getString("Events", R.string.Events)); + headerCell.setText(getString("Events", R.string.Events)); } else if (position == otherSectionRow) { - headerCell.setText(LocaleController.getString("NotificationsOther", R.string.NotificationsOther)); + headerCell.setText(getString("NotificationsOther", R.string.NotificationsOther)); } else if (position == resetSectionRow) { - headerCell.setText(LocaleController.getString("Reset", R.string.Reset)); + headerCell.setText(getString("Reset", R.string.Reset)); } else if (position == callsSectionRow) { - headerCell.setText(LocaleController.getString("VoipNotificationSettings", R.string.VoipNotificationSettings)); + headerCell.setText(getString("VoipNotificationSettings", R.string.VoipNotificationSettings)); } else if (position == badgeNumberSection) { - headerCell.setText(LocaleController.getString("BadgeNumber", R.string.BadgeNumber)); + headerCell.setText(getString("BadgeNumber", R.string.BadgeNumber)); } else if (position == accountsSectionRow) { - headerCell.setText(LocaleController.getString("ShowNotificationsFor", R.string.ShowNotificationsFor)); + headerCell.setText(getString("ShowNotificationsFor", R.string.ShowNotificationsFor)); } break; } @@ -932,35 +960,35 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif TextCheckCell checkCell = (TextCheckCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (position == inappSoundRow) { - checkCell.setTextAndCheck(LocaleController.getString("InAppSounds", R.string.InAppSounds), preferences.getBoolean("EnableInAppSounds", true), true); + checkCell.setTextAndCheck(getString("InAppSounds", R.string.InAppSounds), preferences.getBoolean("EnableInAppSounds", true), true); } else if (position == inappVibrateRow) { - checkCell.setTextAndCheck(LocaleController.getString("InAppVibrate", R.string.InAppVibrate), preferences.getBoolean("EnableInAppVibrate", true), true); + checkCell.setTextAndCheck(getString("InAppVibrate", R.string.InAppVibrate), preferences.getBoolean("EnableInAppVibrate", true), true); } else if (position == inappPreviewRow) { - checkCell.setTextAndCheck(LocaleController.getString("InAppPreview", R.string.InAppPreview), preferences.getBoolean("EnableInAppPreview", true), true); + checkCell.setTextAndCheck(getString("InAppPreview", R.string.InAppPreview), preferences.getBoolean("EnableInAppPreview", true), true); } else if (position == inappPriorityRow) { - checkCell.setTextAndCheck(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), preferences.getBoolean("EnableInAppPriority", false), false); + checkCell.setTextAndCheck(getString("NotificationsImportance", R.string.NotificationsImportance), preferences.getBoolean("EnableInAppPriority", false), false); } else if (position == contactJoinedRow) { - checkCell.setTextAndCheck(LocaleController.getString("ContactJoined", R.string.ContactJoined), preferences.getBoolean("EnableContactJoined", true), true); + checkCell.setTextAndCheck(getString("ContactJoined", R.string.ContactJoined), preferences.getBoolean("EnableContactJoined", true), true); } else if (position == pinnedMessageRow) { - checkCell.setTextAndCheck(LocaleController.getString("PinnedMessages", R.string.PinnedMessages), preferences.getBoolean("PinnedMessages", true), false); + checkCell.setTextAndCheck(getString("PinnedMessages", R.string.PinnedMessages), preferences.getBoolean("PinnedMessages", true), false); } else if (position == androidAutoAlertRow) { checkCell.setTextAndCheck("Android Auto", preferences.getBoolean("EnableAutoNotifications", false), true); } else if (position == notificationsServiceRow) { - checkCell.setTextAndValueAndCheck(LocaleController.getString("NotificationsService", R.string.NotificationsService), LocaleController.getString("NotificationsServiceInfo", R.string.NotificationsServiceInfo), preferences.getBoolean("pushService", getMessagesController().keepAliveService), true, true); + checkCell.setTextAndValueAndCheck(getString("NotificationsService", R.string.NotificationsService), getString("NotificationsServiceInfo", R.string.NotificationsServiceInfo), preferences.getBoolean("pushService", getMessagesController().keepAliveService), true, true); } else if (position == notificationsServiceConnectionRow) { - checkCell.setTextAndValueAndCheck(LocaleController.getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), LocaleController.getString("NotificationsServiceConnectionInfo", R.string.NotificationsServiceConnectionInfo), preferences.getBoolean("pushConnection", getMessagesController().backgroundConnection), true, true); + checkCell.setTextAndValueAndCheck(getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), getString("NotificationsServiceConnectionInfo", R.string.NotificationsServiceConnectionInfo), preferences.getBoolean("pushConnection", getMessagesController().backgroundConnection), true, true); } else if (position == badgeNumberShowRow) { - checkCell.setTextAndCheck(LocaleController.getString("BadgeNumberShow", R.string.BadgeNumberShow), getNotificationsController().showBadgeNumber, true); + checkCell.setTextAndCheck(getString("BadgeNumberShow", R.string.BadgeNumberShow), getNotificationsController().showBadgeNumber, true); } else if (position == badgeNumberMutedRow) { - checkCell.setTextAndCheck(LocaleController.getString("BadgeNumberMutedChats", R.string.BadgeNumberMutedChats), getNotificationsController().showBadgeMuted, true); + checkCell.setTextAndCheck(getString("BadgeNumberMutedChats", R.string.BadgeNumberMutedChats), getNotificationsController().showBadgeMuted, true); } else if (position == badgeNumberMessagesRow) { - checkCell.setTextAndCheck(LocaleController.getString("BadgeNumberUnread", R.string.BadgeNumberUnread), getNotificationsController().showBadgeMessages, false); + checkCell.setTextAndCheck(getString("BadgeNumberUnread", R.string.BadgeNumberUnread), getNotificationsController().showBadgeMessages, false); } else if (position == inchatSoundRow) { - checkCell.setTextAndCheck(LocaleController.getString("InChatSound", R.string.InChatSound), preferences.getBoolean("EnableInChatSound", true), true); + checkCell.setTextAndCheck(getString("InChatSound", R.string.InChatSound), preferences.getBoolean("EnableInChatSound", true), true); } else if (position == callsVibrateRow) { - checkCell.setTextAndCheck(LocaleController.getString("Vibrate", R.string.Vibrate), preferences.getBoolean("EnableCallVibrate", true), true); + checkCell.setTextAndCheck(getString("Vibrate", R.string.Vibrate), preferences.getBoolean("EnableCallVibrate", true), true); } else if (position == accountsAllRow) { - checkCell.setTextAndCheck(LocaleController.getString("AllAccounts", R.string.AllAccounts), MessagesController.getGlobalNotificationsSettings().getBoolean("AllAccounts", true), false); + checkCell.setTextAndCheck(getString("AllAccounts", R.string.AllAccounts), MessagesController.getGlobalNotificationsSettings().getBoolean("AllAccounts", true), false); } break; } @@ -968,7 +996,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif TextDetailSettingsCell settingsCell = (TextDetailSettingsCell) holder.itemView; settingsCell.setMultilineDetail(true); if (position == resetNotificationsRow) { - settingsCell.setTextAndValue(LocaleController.getString("ResetAllNotifications", R.string.ResetAllNotifications), LocaleController.getString("UndoAllCustom", R.string.UndoAllCustom), false); + settingsCell.setTextAndValue(getString("ResetAllNotifications", R.string.ResetAllNotifications), getString("UndoAllCustom", R.string.UndoAllCustom), false); } break; } @@ -983,23 +1011,34 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif ArrayList autoExceptions = null; boolean enabled; boolean allAuto = false; + int icon = 0; if (position == privateRow) { - text = LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats); + text = getString(R.string.NotificationsPrivateChats); exceptions = exceptionUsers; offUntil = preferences.getInt("EnableAll2", 0); + icon = R.drawable.msg_openprofile; } else if (position == groupRow) { - text = LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups); + text = getString(R.string.NotificationsGroups); exceptions = exceptionChats; offUntil = preferences.getInt("EnableGroup2", 0); + icon = R.drawable.msg_groups; } else if (position == storiesRow) { - text = LocaleController.getString("NotificationStories", R.string.NotificationStories); + text = getString(R.string.NotificationStories); exceptions = exceptionStories; autoExceptions = exceptionAutoStories; offUntil = preferences.getBoolean("EnableAllStories", false) ? 0 : Integer.MAX_VALUE; + icon = R.drawable.msg_menu_stories; + } else if (position == reactionsRow) { + text = getString(R.string.NotificationReactions); + exceptions = null; + autoExceptions = null; + offUntil = preferences.getBoolean("EnableReactionsMessages", true) || preferences.getBoolean("EnableReactionsStories", true) ? 0 : Integer.MAX_VALUE; + icon = R.drawable.msg_reactions; } else { - text = LocaleController.getString("NotificationsChannels", R.string.NotificationsChannels); + text = getString(R.string.NotificationsChannels); exceptions = exceptionChannels; offUntil = preferences.getInt("EnableChannel2", 0); + icon = R.drawable.msg_channel; } int iconType; if (enabled = offUntil < currentTime) { @@ -1010,11 +1049,27 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif iconType = 2; } StringBuilder builder = new StringBuilder(); - if (exceptions != null && !exceptions.isEmpty()) { + if (position == reactionsRow) { + if (offUntil > 0) { + enabled = false; + builder.append(getString("NotificationsOff", R.string.NotificationsOff)); + } else { + enabled = true; + if (preferences.getBoolean("EnableReactionsMessages", true)) { + builder.append(getString(R.string.NotificationReactionsMessages)); + } + if (preferences.getBoolean("EnableReactionsStories", true)) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append(getString(R.string.NotificationReactionsStories)); + } + } + } else if (exceptions != null && !exceptions.isEmpty()) { if (enabled = offUntil < currentTime) { - builder.append(LocaleController.getString("NotificationsOn", R.string.NotificationsOn)); + builder.append(getString("NotificationsOn", R.string.NotificationsOn)); } else if (offUntil - 60 * 60 * 24 * 365 >= currentTime) { - builder.append(LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + builder.append(getString("NotificationsOff", R.string.NotificationsOff)); } else { builder.append(LocaleController.formatString("NotificationsOffUntil", R.string.NotificationsOffUntil, LocaleController.stringForMessageListDate(offUntil))); } @@ -1028,18 +1083,18 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif builder.append(LocaleController.formatPluralString("Exception", exceptionsCount)); } else if (autoExceptions != null && !autoExceptions.isEmpty()) { if (offUntil > 0) { - builder.append(LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + builder.append(getString("NotificationsOff", R.string.NotificationsOff)); } else { - builder.append(LocaleController.getString("NotificationsOn", R.string.NotificationsOn)); + builder.append(getString("NotificationsOn", R.string.NotificationsOn)); } if (autoExceptions != null && !autoExceptions.isEmpty() && !preferences.contains("EnableAllStories")) { builder.append(", "); builder.append(LocaleController.formatPluralString("AutoException", autoExceptions.size())); } } else { - builder.append(LocaleController.getString("TapToChange", R.string.TapToChange)); + builder.append(getString("TapToChange", R.string.TapToChange)); } - checkCell.setTextAndValueAndCheck(text, builder, enabled, iconType, position != storiesRow); + checkCell.setTextAndValueAndIconAndCheck(text, builder, icon, enabled, iconType, false, position != reactionsRow); break; } case 4: { @@ -1054,37 +1109,37 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif TextSettingsCell textCell = (TextSettingsCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (position == callsRingtoneRow) { - String value = preferences.getString("CallsRingtone", LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone)); + String value = preferences.getString("CallsRingtone", getString("DefaultRingtone", R.string.DefaultRingtone)); if (value.equals("NoSound")) { - value = LocaleController.getString("NoSound", R.string.NoSound); + value = getString("NoSound", R.string.NoSound); } - textCell.setTextAndValue(LocaleController.getString("VoipSettingsRingtone", R.string.VoipSettingsRingtone), value, updateRingtone, false); + textCell.setTextAndValue(getString("VoipSettingsRingtone", R.string.VoipSettingsRingtone), value, updateRingtone, false); updateRingtone = false; } else if (position == callsVibrateRow) { int value = preferences.getInt("vibrate_calls", 0); if (value == 0) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("VibrationDefault", R.string.VibrationDefault), updateVibrate, true); } else if (value == 1) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("Short", R.string.Short), updateVibrate, true); } else if (value == 2) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("VibrationDisabled", R.string.VibrationDisabled), updateVibrate, true); } else if (value == 3) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Long", R.string.Long), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("Long", R.string.Long), updateVibrate, true); } else if (value == 4) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("OnlyIfSilent", R.string.OnlyIfSilent), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("OnlyIfSilent", R.string.OnlyIfSilent), updateVibrate, true); } updateVibrate = false; } else if (position == repeatRow) { int minutes = preferences.getInt("repeat_messages", 60); String value; if (minutes == 0) { - value = LocaleController.getString("RepeatNotificationsNever", R.string.RepeatNotificationsNever); + value = getString("RepeatNotificationsNever", R.string.RepeatNotificationsNever); } else if (minutes < 60) { value = LocaleController.formatPluralString("Minutes", minutes); } else { value = LocaleController.formatPluralString("Hours", minutes / 60); } - textCell.setTextAndValue(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications), value, updateRepeatNotifications, false); + textCell.setTextAndValue(getString("RepeatNotifications", R.string.RepeatNotifications), value, updateRepeatNotifications, false); updateRepeatNotifications = false; } break; @@ -1092,7 +1147,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif case 6: { TextInfoPrivacyCell textCell = (TextInfoPrivacyCell) holder.itemView; if (position == accountsInfoRow) { - textCell.setText(LocaleController.getString("ShowNotificationsForInfo", R.string.ShowNotificationsForInfo)); + textCell.setText(getString("ShowNotificationsForInfo", R.string.ShowNotificationsForInfo)); } break; } @@ -1113,7 +1168,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif return 1; } else if (position == resetNotificationsRow) { return 2; - } else if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow) { + } else if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow || position == reactionsRow) { return 3; } else if (position == eventsSection2Row || position == notificationsSection2Row || position == otherSection2Row || position == resetSection2Row || position == callsSection2Row || position == badgeNumberSection2Row || diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java index 262dba1bb..0fc866514 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java @@ -152,6 +152,9 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta } else if (currentType == NotificationsController.TYPE_STORIES) { prefPath = "StoriesSoundPath"; prefDocId = "StoriesSoundDocId"; + } else if (currentType == NotificationsController.TYPE_REACTIONS_MESSAGES || currentType == NotificationsController.TYPE_REACTIONS_STORIES) { + prefPath = "ReactionSoundPath"; + prefDocId = "ReactionSoundDocId"; } else { throw new RuntimeException("Unsupported type"); } @@ -294,7 +297,9 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta } else if (currentType == NotificationsController.TYPE_CHANNEL) { actionBar.setTitle(LocaleController.getString("NotificationsSoundChannels", R.string.NotificationsSoundChannels)); } else if (currentType == NotificationsController.TYPE_STORIES) { - actionBar.setTitle(LocaleController.getString("NotificationsSoundStories", R.string.NotificationsSoundStories)); + actionBar.setTitle(LocaleController.getString(R.string.NotificationsSoundStories)); + } else if (currentType == NotificationsController.TYPE_REACTIONS_STORIES || currentType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + actionBar.setTitle(LocaleController.getString(R.string.NotificationsSoundReactions)); } } else { avatarContainer = new ChatAvatarContainer(context, null, false, resourcesProvider); @@ -885,6 +890,10 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta prefName = "StoriesSound"; prefPath = "StoriesSoundPath"; prefDocId = "StoriesSoundDocId"; + } else if (currentType == NotificationsController.TYPE_REACTIONS_STORIES || currentType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + prefName = "ReactionSound"; + prefPath = "ReactionSoundPath"; + prefDocId = "ReactionSoundDocId"; } else { throw new RuntimeException("Unsupported type"); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index 2ee98762a..d5272d249 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -6319,6 +6319,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter req.settings.allow_flashcall = false; } } else { + req.settings.unknown_number = true; req.settings.current_number = false; } } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java index 29e7544ac..eaf6ea7d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java @@ -1171,6 +1171,33 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { shouldNavigateBack = !url.equals(webViewUrl); + try { + Uri uri = Uri.parse(url); + if ("t.me".equals(uri.getHost())) { + goToNextStep(); + return true; + } + + if (BLACKLISTED_PROTOCOLS.contains(uri.getScheme())) { + return true; + } + if (!WEBVIEW_PROTOCOLS.contains(uri.getScheme())) { + try { + if (getContext() instanceof Activity) { + ((Activity) getContext()).startActivityForResult(new Intent(Intent.ACTION_VIEW, uri), BasePermissionsActivity.REQUEST_CODE_PAYMENT_FORM); + } + } catch (ActivityNotFoundException e) { + new AlertDialog.Builder(context) + .setTitle(currentBotName) + .setMessage(LocaleController.getString(R.string.PaymentAppNotFoundForDeeplink)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .show(); + } + return true; + } + } catch (Exception ignore) { + + } return super.shouldOverrideUrlLoading(view, url); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 59453aca1..defbf4dad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -55,6 +55,7 @@ import android.graphics.drawable.GradientDrawable; import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.net.Uri; +import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; @@ -111,6 +112,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.OverScroller; import android.widget.Scroller; +import android.widget.Space; import android.widget.TextView; import android.widget.Toast; @@ -232,6 +234,7 @@ import org.telegram.ui.Components.MediaActivity; import org.telegram.ui.Components.OptionsSpeedIconDrawable; import org.telegram.ui.Components.OtherDocumentPlaceholderDrawable; import org.telegram.ui.Components.Paint.Views.LPhotoPaintView; +import org.telegram.ui.Components.Paint.Views.MaskPaintView; import org.telegram.ui.Components.Paint.Views.StickerCutOutBtn; import org.telegram.ui.Components.Paint.Views.StickerMakerView; import org.telegram.ui.Components.Paint.Views.StickerMakerBackgroundView; @@ -780,6 +783,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public static final int EDIT_MODE_CROP = 1; public static final int EDIT_MODE_FILTER = 2; public static final int EDIT_MODE_PAINT = 3; + public static final int EDIT_MODE_STICKER_MASK = 4; private int videoWidth, videoHeight; private float inlineOutAnimationProgress; @@ -860,6 +864,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private AnimatorSet paintKeyboardAnimator; private KeyboardNotifier paintKeyboardNotifier; private LPhotoPaintView photoPaintView; + private boolean maskPaintViewEraser; + private MaskPaintView maskPaintView; + private boolean maskPaintViewShuttingDown; private AlertDialog visibleDialog; private CaptionTextViewSwitcher captionTextViewSwitcher; private CaptionScrollView captionScrollView; @@ -1848,9 +1855,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat boolean fromCamera; private boolean captionTranslated; private String captionDetectedLanguage; - private StickerMakerView stickerMakerView; + public StickerMakerView stickerMakerView; + private ArrayList selectedEmojis; private StickerMakerBackgroundView stickerMakerBackgroundView; - private StickerCutOutBtn cutOutBtn; + private BlurButton cutOutBtn; + private LinearLayout btnLayout; + private BlurButton eraseBtn, restoreBtn, undoBtn, outlineBtn; private long avatarsDialogId; private boolean canEditAvatar; @@ -1891,6 +1901,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private float animateToScale; private float animateToRotate; private float animateToMirror; + private float savedTx, savedTy, savedScale, savedRotation; private float animationValue; private float clippingImageProgress; private boolean applying; @@ -1902,7 +1913,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean doubleTapEnabled; private DecelerateInterpolator interpolator = new DecelerateInterpolator(1.5f); private float pinchStartDistance; + private float pinchStartAngle; private float pinchStartScale = 1; + private float pinchStartRotate = 0; private float pinchCenterX; private float pinchCenterY; private float pinchStartX; @@ -1918,6 +1931,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean zooming; private boolean moving; private int paintViewTouched; + private int maskPaintViewTouched; private boolean doubleTap; private boolean invalidCoords; private boolean canDragDown = true; @@ -2984,7 +2998,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } private ArrayList exclusionRects; - + public void updateExclusionRects() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (exclusionRects == null) { @@ -4299,6 +4313,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (captionEdit != null) { captionEdit.setAccount(currentAccount); } + if (stickerMakerView != null) { + stickerMakerView.setCurrentAccount(currentAccount); + } if (parentActivity == activity || activity == null) { updateColors(); return; @@ -4492,11 +4509,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override protected void onDraw(Canvas canvas) { - if (stickerMakerBackgroundView != null) { + if (stickerMakerBackgroundView != null && stickerMakerBackgroundView.getVisibility() == View.VISIBLE) { View parent = (View) stickerMakerBackgroundView.getParent(); float alpha = Math.min(stickerMakerBackgroundView.getAlpha(), parent != null ? parent.getAlpha() : 1f); if (alpha > 0) { - canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) alpha * 255, Canvas.ALL_SAVE_FLAG); + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); stickerMakerBackgroundView.draw(canvas); canvas.restore(); } @@ -4564,6 +4581,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat View overlay = textSelectionHelper.getOverlayView(windowView.getContext()); overlay.draw(canvas); } + + @Override + protected void onLayout(boolean changed, int _l, int t, int _r, int _b) { + if (btnLayout != null && undoBtn != null) { + int sz = _r - _l - dp(20); + undoBtn.setTranslationY(-sz / 2f - dp(29 + 18)); + btnLayout.setTranslationY(sz / 2f + dp(29 + 18)); + cutOutBtn.setTranslationY(sz / 2f + dp(29 + 18)); + outlineBtn.setTranslationY(sz / 2f + dp(29 + 18 + 36 + 12)); + } + super.onLayout(changed, _l, t, _r, _b); + } }; containerView.setFocusable(false); @@ -5787,15 +5816,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (captionEdit != null && captionEdit.getVisibility() != GONE) { captionEdit.setAlpha(alpha); } - if (cutOutBtn != null && cutOutBtn.getVisibility() != GONE) { - cutOutBtn.setAlpha(alpha); - } - if (stickerMakerView != null && stickerMakerView.getVisibility() != GONE) { - stickerMakerView.setAlpha(alpha); - } - if (stickerMakerBackgroundView != null && stickerMakerBackgroundView.getVisibility() != GONE) { - stickerMakerBackgroundView.setAlpha(alpha); - } } @Override @@ -6105,7 +6125,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat }); captionEdit.setAccount(currentAccount); captionEdit.setOnHeightUpdate(height -> { - videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, height - dp(46))); + if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != View.GONE) { + videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46))); + } muteItem.setTranslationY(-Math.max(0, height - dp(46))); }); captionEdit.setOnAddPhotoClick(v -> { @@ -6123,29 +6145,21 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowView.invalidate(); } }; + stickerMakerBackgroundView.setVisibility(View.GONE); containerView.addView(stickerMakerBackgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); stickerMakerView = new StickerMakerView(activityContext, resourcesProvider); stickerMakerView.setCurrentAccount(currentAccount); containerView.addView(stickerMakerView, containerView.indexOfChild(actionBar) - 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); - cutOutBtn = new StickerCutOutBtn(stickerMakerView, activityContext, resourcesProvider, blurManager) { - private final Path path = new Path(); - - @Override - protected void onDraw(Canvas canvas) { - canvas.save(); - path.rewind(); - path.addRoundRect(bounds, dp(8), dp(8), Path.Direction.CW); - canvas.clipPath(path); - canvas.translate(-getX(), -getY()); - drawCaptionBlur(canvas, blurDrawer, 0xFF2b2b2b, 0x33000000, false, true, false); - canvas.restore(); - super.onDraw(canvas); - } - }; + cutOutBtn = new BlurButton(); + cutOutBtn.setRad(18); + cutOutBtn.wrapContentDynamic(); stickerMakerView.setStickerCutOutBtn(cutOutBtn); cutOutBtn.setOnClickListener(v -> { - if (cutOutBtn.isLoading()) { + if (stickerEmpty) { + return; + } + if (cutOutBtn.isLoading() || cutOutBtn.isUndoCutState()) { return; } if (currentIndex < 0 || currentIndex >= imagesArrLocals.size() || stickerMakerView.isThanosInProgress) { @@ -6167,7 +6181,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (thanosEffect == null/* || photoEntry.isCropped || centerImage.getOrientation() == 180*/) { centerImage.setImageBitmap(segmentedImage); cutOutBtn.setUndoCutState(true); - cutOutBtn.postDelayed(this::applyCurrentEditMode, 250); + showStickerMode(true, true); + cutOutBtn.post(this::applyCurrentEditMode); return; } @@ -6175,17 +6190,34 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (bitmap == null) { centerImage.setImageBitmap(segmentedImage); cutOutBtn.setUndoCutState(true); - cutOutBtn.postDelayed(this::applyCurrentEditMode, 250); + showStickerMode(true, true); + cutOutBtn.post(this::applyCurrentEditMode); return; } if (entry.cropState != null) { bitmap = createCroppedBitmap(bitmap, entry.cropState, new int[]{centerImage.getOrientation(), centerImage.getInvert()}, true); } + if (bitmap == null) { + centerImage.setImageBitmap(segmentedImage); + cutOutBtn.setUndoCutState(true); + showEditStickerMode(true, true); + cutOutBtn.post(this::applyCurrentEditMode); + return; + } Matrix matrix = new Matrix(); - float w = getContainerViewWidth(), h = stickerMakerView.getSegmentBorderImageHeight(); + int BW = bitmap.getWidth(), BH = bitmap.getHeight(); + if (!photoEntry.isCropped && centerImage.getOrientation() / 90 % 2 != 0) { + BW = bitmap.getHeight(); + BH = bitmap.getWidth(); + } + float scale = Math.min( + (float) getContainerViewWidth() / BW, + (float) getContainerViewHeight() / BH + ); + float w = BW * scale, h = BH * scale; float tx = 0, ty = 0; - if (centerImage.getOrientation() != 0 && !photoEntry.isCropped) { + if (centerImage.getOrientation() != 0 && !photoEntry.isCropped || rotate != 0) { final float bw = bitmap.getWidth(); final float bh = bitmap.getHeight(); final float r = (float) Math.sqrt((bw / 2f) * (bw / 2f) + (bh / 2f) * (bh / 2f)); @@ -6193,7 +6225,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Bitmap newBitmap = Bitmap.createBitmap((int) d, (int) d, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(newBitmap); canvas.save(); - canvas.rotate(centerImage.getOrientation(), r, r); + canvas.rotate((photoEntry.isCropped ? 0 : centerImage.getOrientation()) + rotate, r, r); canvas.drawBitmap(bitmap, (d - bw) / 2, (d - bh) / 2, null); bitmap.recycle(); bitmap = newBitmap; @@ -6205,20 +6237,27 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat h = pd; } matrix.postScale(w, h); - matrix.postScale(scale, scale, w / 2f, h / 2f); - int marginTop = (int) ((getContainerViewHeight() - stickerMakerView.getSegmentBorderImageHeight()) / 2f); - matrix.postTranslate(translationX + tx, translationY + ty + marginTop); + matrix.postScale(this.scale, this.scale, w / 2f, h / 2f); + matrix.postTranslate( + translationX + tx + Math.max(0, (int) ((getContainerViewWidth() - BW * scale) / 2f)), + translationY + ty + Math.max(0, (int) ((getContainerViewHeight() - BH * scale) / 2f)) + ); stickerMakerView.isThanosInProgress = true; + Utilities.themeQueue.postRunnable(() -> { + applyCurrentEditMode(segmentedImage); + }); + Runnable turnOff = () -> stickerMakerView.isThanosInProgress = false; thanosEffect.animate(matrix, bitmap, () -> { centerImage.setImageBitmap(segmentedImage); cutOutBtn.setUndoCutState(true); - cutOutBtn.postDelayed(() -> { - applyCurrentEditMode(); - stickerMakerView.isThanosInProgress = false; - }, 1000); + showStickerMode(true, true); + AndroidUtilities.cancelRunOnUIThread(turnOff); + AndroidUtilities.runOnUIThread(turnOff, 800); }, () -> {}); + AndroidUtilities.runOnUIThread(turnOff, 1200); } else { cutOutBtn.setCutOutState(true); + showEditStickerMode(false, true); } stickerMakerView.disableClippingMode(); containerView.invalidate(); @@ -6226,17 +6265,98 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.invalidate(); } else if (cutOutBtn.isCancelState()) { cutOutBtn.setCutOutState(true); + showEditStickerMode(false, true); stickerMakerView.disableClippingMode(); containerView.invalidate(); } else { + stickerMakerView.resetPaths(); + stickerMakerView.getThanosEffect(); stickerMakerView.setSegmentedState(false, null); centerImage.setImageBitmap(stickerMakerView.getSourceBitmap(hasFilters)); cutOutBtn.setCutOutState(true); - cutOutBtn.postDelayed(this::applyCurrentEditMode, 250); + showEditStickerMode(false, true); + applyCurrentEditMode(); } }); cutOutBtn.setCutOutState(false); - containerView.addView(cutOutBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 10, 0, 10, 48 + 24)); + containerView.addView(cutOutBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.CENTER)); + + btnLayout = new LinearLayout(parentActivity); + btnLayout.setOrientation(LinearLayout.HORIZONTAL); + + eraseBtn = new BlurButton(); + eraseBtn.wrapContent(); + eraseBtn.setRad(18); + eraseBtn.setEraseState(false); + eraseBtn.setOnClickListener(v -> { + eraseBtn.setActive(true, true); + restoreBtn.setActive(false, true); + if (stickerMakerView != null) { + stickerMakerView.setOutlineVisible(false); + } + maskPaintViewEraser = true; + if (maskPaintView != null) { + maskPaintView.setEraser(maskPaintViewEraser); + } + switchToEditMode(EDIT_MODE_STICKER_MASK); + }); + btnLayout.addView(eraseBtn, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36)); + + btnLayout.addView(new Space(parentActivity), LayoutHelper.createLinear(12, LayoutHelper.MATCH_PARENT)); + + restoreBtn = new BlurButton(); + restoreBtn.wrapContent(); + restoreBtn.setRad(18); + restoreBtn.setRestoreState(false); + restoreBtn.setOnClickListener(v -> { + eraseBtn.setActive(false, true); + restoreBtn.setActive(true, true); + if (stickerMakerView != null) { + stickerMakerView.setOutlineVisible(false); + } + maskPaintViewEraser = false; + if (maskPaintView != null) { + maskPaintView.setEraser(maskPaintViewEraser); + } + switchToEditMode(EDIT_MODE_STICKER_MASK); + }); + btnLayout.addView(restoreBtn, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36)); + + containerView.addView(btnLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER)); + + undoBtn = new BlurButton(); + undoBtn.setUndoState(false); + undoBtn.setRad(18); + undoBtn.wrapContent(); + undoBtn.setOnClickListener(v -> { + if (maskPaintView == null || !maskPaintView.undo()) { + switchToEditMode(EDIT_MODE_NONE); + stickerMakerView.resetPaths(); + MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); + boolean hasFilters = !TextUtils.isEmpty(entry.filterPath); + if (stickerMakerView != null && !stickerMakerView.empty) { + stickerMakerView.setSegmentedState(false, null); + } + centerImage.setImageBitmap(stickerMakerView.getSourceBitmap(hasFilters)); + if (stickerMakerView == null || !stickerMakerView.empty) { + cutOutBtn.setCutOutState(true); + } + showStickerMode(true, true); + } + }); + containerView.addView(undoBtn, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER)); + + outlineBtn = new BlurButton(); + outlineBtn.setOutlineState(false); + outlineBtn.setRad(18); + outlineBtn.wrapContent(); + outlineBtn.setOnClickListener(v -> { + if (stickerMakerView != null) { + outlineBtn.setActive(!outlineBtn.isActive(), true); + stickerMakerView.setOutlineVisible(outlineBtn.isActive() && !(eraseBtn.isActive() || restoreBtn.isActive())); + } + }); + containerView.addView(outlineBtn, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER)); showEditCaption(false, false); showStickerMode(false, false); @@ -6288,6 +6408,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (placeProvider != null && !placeProvider.allowSendingSubmenu()) { return false; } + if (sendPhotoType == SELECT_TYPE_STICKER) { + return false; + } boolean isStoryViewer = parentFragment != null && parentFragment.getLastStoryViewer() != null; if (!isStoryViewer && (parentChatActivity == null || parentChatActivity.isInScheduleMode())) { return false; @@ -6594,6 +6717,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat tuneItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(tuneItem, LayoutHelper.createLinear(48, 48)); tuneItem.setOnClickListener(v -> { + if (v.getAlpha() < .9f) return; cancelStickerClippingMode(); if (isCaptionOpen()) { return; @@ -7025,121 +7149,208 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (object instanceof MediaController.PhotoEntry) { int stickerMaxSize = 512; MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); - String path = photoEntry.imagePath != null ? photoEntry.imagePath : photoEntry.path; - Bitmap paintBitmap = BitmapFactory.decodeFile(path); Bitmap canvasBitmap = Bitmap.createBitmap(stickerMaxSize, stickerMaxSize, Bitmap.Config.ARGB_8888); - float scaleImage = Math.min( - (float) getContainerViewWidth() / paintBitmap.getWidth(), - (float) getContainerViewHeight() / paintBitmap.getHeight() - ) / (getContainerViewWidth() - dp(20)) * canvasBitmap.getWidth() * scale; - float scaleContainer = (float) canvasBitmap.getWidth() / (getContainerViewWidth() - dp(20)); - Canvas canvas = new Canvas(canvasBitmap); - Matrix matrix = new Matrix(); - if (centerImage.getOrientation() != 0 && !(photoEntry.isPainted || photoEntry.isCropped)) { - float cx = paintBitmap.getWidth() / 2f; - float cy = paintBitmap.getHeight() / 2f; - matrix.postRotate(centerImage.getOrientation(), cx, cy); - float scaleFactor = paintBitmap.getWidth() / (float) paintBitmap.getHeight(); - matrix.postScale(scaleFactor, scaleFactor, cx, cy); - } - - matrix.postScale(scaleImage, scaleImage); - float newSrcImgWidth = paintBitmap.getWidth() * scaleImage; - float newSrcImgHeight = paintBitmap.getHeight() * scaleImage; - float dyToCenter = -(newSrcImgHeight - canvasBitmap.getHeight()) / 2; - float dxToCenter = -(newSrcImgWidth - canvasBitmap.getWidth()) / 2; - matrix.postTranslate(dxToCenter, dyToCenter); - - matrix.postTranslate(translationX * scaleContainer, translationY * scaleContainer); Path clipPath = new Path(); RectF clipRect = new RectF(); clipRect.set(0, 0, canvasBitmap.getWidth(), canvasBitmap.getHeight()); int r = canvasBitmap.getWidth() / 8; clipPath.addRoundRect(clipRect, r, r, Path.Direction.CW); canvas.clipPath(clipPath); - canvas.drawBitmap(paintBitmap, matrix, new Paint(Paint.FILTER_BITMAP_FLAG)); - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(canvasBitmap, Bitmap.CompressFormat.WEBP, stickerMaxSize, stickerMaxSize, 100, false, 101, 101); - final String fullStickerPath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(size, "webp", true).toString(); + int containerWidth = getContainerViewWidth(); + int containerHeight = getContainerViewHeight(); + float borderSize = containerWidth - dp(20); + if (stickerMakerView != null && stickerMakerView.outlineVisible && stickerMakerView.getSourceBitmap() != null) { + + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + stickerMakerView.drawOutline(canvas, false, null, false); + canvas.restore(); + + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + centerImage.draw(canvas); + canvas.restore(); + + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + stickerMakerView.drawOutline(canvas, true, null, false); + canvas.restore(); + } else { + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + centerImage.draw(canvas); + canvas.restore(); + } + + if (paintingOverlay != null) { + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + canvas.translate(-centerImage.getImageWidth() / 2f, -centerImage.getImageHeight() / 2f); + canvas.scale(centerImage.getImageWidth() / paintingOverlay.getMeasuredWidth(), centerImage.getImageHeight() / paintingOverlay.getMeasuredHeight()); + paintingOverlay.drawChildren = !hasAnimatedMediaEntities(); + paintingOverlay.draw(canvas); + paintingOverlay.drawChildren = true; + canvas.restore(); + } + + String stickerEmoji = null; VideoEditedInfo videoEditedInfo1 = null; if (hasAnimatedMediaEntities()) { + Matrix matrix = new Matrix(); + matrix.reset(); + matrix.preTranslate(borderSize / 2f, borderSize / 2f); + applyTransformToMatrix(matrix); + matrix.preTranslate(-centerImage.getImageWidth() / 2f, -centerImage.getImageHeight() / 2f); + matrix.preScale(centerImage.getImageWidth(), centerImage.getImageHeight()); + ArrayList entities = new ArrayList<>(); for (VideoEditedInfo.MediaEntity entity : photoEntry.mediaEntities) { VideoEditedInfo.MediaEntity e = entity.copy(); - AndroidUtilities.rectTmp.set( - e.x * paintBitmap.getWidth(), - e.y * paintBitmap.getHeight(), - (e.x + e.width) * paintBitmap.getWidth(), - (e.y + e.height) * paintBitmap.getHeight() - ); - matrix.mapRect(AndroidUtilities.rectTmp); - e.x = AndroidUtilities.rectTmp.left / canvasBitmap.getWidth(); - e.y = AndroidUtilities.rectTmp.top / canvasBitmap.getHeight(); - e.width = AndroidUtilities.rectTmp.width() / canvasBitmap.getWidth(); - e.height = AndroidUtilities.rectTmp.height() / canvasBitmap.getHeight(); - e.scale *= scaleImage; + float x = e.x; + float y = e.y; + float w = e.width; + float h = e.height; + float pos[] = new float[] { + x, y, + x + w, y, + x + w, y + h, + x, y + h + }; + matrix.mapPoints(pos); + e.width = (float) Math.sqrt(Math.pow(pos[0] - pos[2], 2) + Math.pow(pos[1] - pos[3], 2)) / borderSize; + e.height = (float) Math.sqrt(Math.pow(pos[0] - pos[6], 2) + Math.pow(pos[1] - pos[7], 2)) / borderSize; + e.x = ((pos[0] + pos[4]) / 2f) / borderSize - e.width / 2f; + e.y = ((pos[1] + pos[5]) / 2f) / borderSize - e.height / 2f; + e.scale = 1f; + e.customTextView = true; + if (photoEntry.isCropped && photoEntry.cropState != null) { + e.rotation -= photoEntry.cropState.transformRotation / 180f * Math.PI; + } + e.rotation -= rotate / 180f * Math.PI; entities.add(e); + if (e.document != null && stickerEmoji == null) { + stickerEmoji = MessageObject.findAnimatedEmojiEmoticon(e.document, null); + } } videoEditedInfo1 = new VideoEditedInfo(); - videoEditedInfo1.originalPath = fullStickerPath; videoEditedInfo1.isPhoto = true; videoEditedInfo1.originalWidth = videoEditedInfo1.resultWidth = stickerMaxSize; videoEditedInfo1.originalHeight = videoEditedInfo1.resultHeight = stickerMaxSize; videoEditedInfo1.mediaEntities = entities; - videoEditedInfo1.originalDuration = videoEditedInfo1.estimatedDuration = Utilities.clamp(photoEntry.averageDuration, 2800L, 800L); - videoEditedInfo1.bitrate = (int) (255 * 1024 * 8 / (videoEditedInfo1.originalDuration / 1000.0) * 0.24); + videoEditedInfo1.originalDuration = videoEditedInfo1.estimatedDuration = Utilities.clamp(photoEntry.averageDuration, 2999L, 800L); + videoEditedInfo1.bitrate = 200_000; videoEditedInfo1.framerate = 30; videoEditedInfo1.isSticker = true; - videoEditedInfo1.estimatedSize = 256 * 1024 * 8; + videoEditedInfo1.estimatedSize = 256 * 1024; } - if (photoEntry.thumbPath != null) { - try { - new File(photoEntry.thumbPath).delete(); - } catch (Exception e) { - FileLog.e(e); - } - photoEntry.thumbPath = null; + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(canvasBitmap, Bitmap.CompressFormat.WEBP, stickerMaxSize, stickerMaxSize, 100, false, 101, 101); + final String fullStickerPath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(size, "webp", true).toString(); + if (videoEditedInfo1 != null) { + videoEditedInfo1.originalPath = fullStickerPath; } - if (photoEntry.fullPaintPath != null) { - try { - Bitmap paintBitmap2 = BitmapFactory.decodeFile(photoEntry.fullPaintPath); - canvas.drawBitmap(paintBitmap2, matrix, new Paint(Paint.FILTER_BITMAP_FLAG)); - paintBitmap2.recycle(); - } catch (Exception e) { - FileLog.e(e); - } - } - size = ImageLoader.scaleAndSaveImage(canvasBitmap, getCompressFormat(), thumbSize, thumbSize, 83, false, 101, 101); - photoEntry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); VideoEditedInfo finalVideoEditedInfo = videoEditedInfo1; + if (selectedEmojis == null) { + selectedEmojis = new ArrayList<>(); + } + if (selectedEmojis.isEmpty()) { + if (stickerMakerView.detectedEmoji != null && Emoji.getEmojiDrawable(stickerMakerView.detectedEmoji) != null) { + selectedEmojis.add(stickerMakerView.detectedEmoji); + } else if (stickerEmoji != null) { + selectedEmojis.add(stickerEmoji); + } else { + selectedEmojis.add("👍"); + } + } + doneButtonPressed = false; - ContentPreviewViewer.getInstance().showCustomStickerActions(fullStickerPath, videoEditedInfo1, stickerMakerView, new ContentPreviewViewer.ContentPreviewViewerDelegate() { + ContentPreviewViewer.getInstance().showCustomStickerActions(fullStickerPath, videoEditedInfo1, stickerMakerView, selectedEmojis, new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker() { + if (placeProvider == null) + return; + stickerEmptySent = true; + generateThumb(); photoEntry.imagePath = fullStickerPath; placeProvider.sendButtonPressed(currentIndex, finalVideoEditedInfo, notify, scheduleDate, forceDocument); NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, true); } + private void generateThumb() { + ContentPreviewViewer viewer = ContentPreviewViewer.getInstance(); + if (photoEntry.thumbPath != null) { + try { + new File(photoEntry.thumbPath).delete(); + } catch (Exception e) { + FileLog.e(e); + } + photoEntry.thumbPath = null; + } + Bitmap bitmap = Bitmap.createBitmap(thumbSize, thumbSize, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + if (viewer.centerImage != null) { + viewer.centerImage.setAlpha(1f); + viewer.centerImage.setImageCoords(0, 0, bitmap.getWidth(), bitmap.getHeight()); + viewer.centerImage.draw(canvas); + } + if (viewer.paintingOverlay != null) { + canvas.save(); + canvas.scale((float) bitmap.getWidth() / viewer.paintingOverlay.getWidth(), (float) bitmap.getHeight() / viewer.paintingOverlay.getHeight()); + viewer.paintingOverlay.setAlpha(1f); + Path paintingOverlayClipPath = new Path(); + paintingOverlayClipPath.rewind(); + AndroidUtilities.rectTmp.set(0, 0, viewer.paintingOverlay.getWidth(), viewer.paintingOverlay.getHeight()); + paintingOverlayClipPath.addRoundRect(AndroidUtilities.rectTmp, viewer.paintingOverlay.getWidth() / 8f, viewer.paintingOverlay.getHeight() / 8f, Path.Direction.CW); + canvas.clipPath(paintingOverlayClipPath); + viewer.paintingOverlay.draw(canvas); + canvas.restore(); + } + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, getCompressFormat(), thumbSize, thumbSize, 83, false, 101, 101); + photoEntry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + @Override public void addToFavoriteSelected(String emoji) { - stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, true, null, null); + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, true, null, null, photoEntry.thumbPath, null, null); } @Override public void stickerSetSelected(TLRPC.StickerSet stickerSet, String emoji) { - stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, false, stickerSet, replacedSticker); + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, false, stickerSet, replacedSticker, photoEntry.thumbPath, null, null); } @Override - public void newStickerPackSelected(CharSequence name, String emoji) { - stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, name, false, null, null); + public void newStickerPackSelected(CharSequence name, String emoji, Utilities.Callback whenDone) { + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, name, false, null, null, photoEntry.thumbPath, whenDone, null); + } + + @Override + public void setIntroSticker(String emoji) { + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, false, null, null, photoEntry.thumbPath, null, customStickerHandler); } @Override @@ -7147,6 +7358,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return replacedSticker != null; } + @Override + public boolean isSettingIntroSticker() { + return customStickerHandler != null; + } + @Override public long getDialogId() { return currentDialogId; @@ -7825,10 +8041,35 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } private float scale1() { + return scale1(true); + } + + private float scale1(boolean fit) { if (sendPhotoType == SELECT_TYPE_STICKER) { int width = getContainerViewWidth(); if (width == 0) width = AndroidUtilities.displaySize.x; - return (width - dp(20) + 1) / (float) width; + float scale = (width - dp(20) + 1) / (float) width; + if (fit) { + int w = centerImage.getBitmapWidth(); + int h = centerImage.getBitmapHeight(); + if ((w <= 1 || h <= 1) && currentIndex >= 0 && currentIndex < imagesArrLocals.size()) { + Object object = imagesArrLocals.get(currentIndex); + if (object instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); + if (photoEntry.orientation / 90 % 2 != 0) { + w = photoEntry.height; + h = photoEntry.width; + } else { + w = photoEntry.width; + h = photoEntry.height; + } + } + } + if (w > 1 && h > 1 && w > h) { + scale *= (float) w / h; + } + } + return scale; } return 1f; } @@ -7870,8 +8111,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animateToScale = newScale / oldScale; } if (sendPhotoType == SELECT_TYPE_STICKER) { - scale *= scale1(); - animateToScale *= scale1(); + scale *= scale1(false); + animateToScale *= scale1(false); } ValueAnimator areaRotateAnimator = ValueAnimator.ofFloat(0, 1f); final float wasRotation = photoCropView.wheelView.getRotation(); @@ -7891,9 +8132,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imageMoveAnimation = null; rotate = animateToRotate = 0; mirror = animateToMirror = 0; - scale = animateToScale = scale1(); + scale = animateToScale = scale1(false); containerView.invalidate(); - photoCropView.cropView.areaView.setRotationScaleTranslation(0, scale1(), 0, 0); + photoCropView.cropView.areaView.setRotationScaleTranslation(0, scale1(false), 0, 0); photoCropView.wheelView.setRotated(false); if (Math.abs(diff) > 0) { if (photoCropView.rotate(diff)) { @@ -8096,9 +8337,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int min = dp(10); int max = videoPlayerControlFrameLayout.getMeasuredWidth() - dp(10) - videoPreviewFrame.getMeasuredWidth() / 2; if (x < min) { + videoPreviewFrame.setPivotX(Utilities.clamp(videoPreviewFrame.getMeasuredWidth() / 2f - (min - x), videoPreviewFrame.getMeasuredWidth(), 0)); x = min; } else if (x >= max) { + videoPreviewFrame.setPivotX(Utilities.clamp(videoPreviewFrame.getMeasuredWidth() / 2f + (x - max), videoPreviewFrame.getMeasuredWidth(), 0)); x = max; + } else { + videoPreviewFrame.setPivotX(videoPreviewFrame.getMeasuredWidth() / 2f); } videoPreviewFrame.setTranslationX(x); } @@ -8116,14 +8361,20 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } videoPreviewFrame.setTag(show ? 1 : null); videoPreviewFrameAnimation = new AnimatorSet(); - videoPreviewFrameAnimation.playTogether(ObjectAnimator.ofFloat(videoPreviewFrame, View.ALPHA, show ? 1.0f : 0.0f)); + videoPreviewFrameAnimation.playTogether( + ObjectAnimator.ofFloat(videoPreviewFrame, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(videoPreviewFrame, View.SCALE_X, show ? 1.0f : 0.5f), + ObjectAnimator.ofFloat(videoPreviewFrame, View.SCALE_Y, show ? 1.0f : 0.5f), + ObjectAnimator.ofFloat(videoPreviewFrame, View.TRANSLATION_Y, show ? 0f : dp(12)) + ); + videoPreviewFrameAnimation.setDuration(380); + videoPreviewFrameAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); videoPreviewFrameAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { videoPreviewFrameAnimation = null; } }); - videoPreviewFrameAnimation.setDuration(180); videoPreviewFrameAnimation.start(); } @@ -9682,6 +9933,109 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return null; } + private Matrix createCroppedMatrix(int w, int h, MediaController.CropState cropState, int[] extraTransform, boolean mirror) { + try { + int tr = (cropState.transformRotation + (extraTransform != null ? extraTransform[0] : 0)) % 360; + int inv = extraTransform != null && extraTransform.length > 1 ? extraTransform[1] : 0; + int fw = w, rotatedW = w; + int fh = h, rotatedH = h; + if (tr == 90 || tr == 270) { + int temp = fw; + fw = rotatedW = fh; + fh = rotatedH = temp; + } + fw *= cropState.cropPw; + fh *= cropState.cropPh; + Matrix matrix = new Matrix(); + matrix.postTranslate(-w / 2, -h / 2); + if (mirror && cropState.mirrored) { + if (tr == 90 || tr == 270) { + matrix.postScale(1, -1); + } else { + matrix.postScale(-1, 1); + } + } + if (inv == 1) { + matrix.postScale(-1, 1); + } else if (inv == 2) { + matrix.postScale(1, -1); + } + matrix.postRotate(cropState.cropRotate + tr); + matrix.postTranslate(cropState.cropPx * rotatedW, cropState.cropPy * rotatedH); + matrix.postScale(cropState.cropScale, cropState.cropScale); + matrix.postTranslate(fw / 2, fh / 2); + return matrix; + } catch (Throwable e) { + FileLog.e(e); + } + return null; + } + + private void applyCurrentEditMode(Bitmap bitmap) { + Bitmap[] paintThumbBitmap = new Bitmap[1]; + int[] orientation = null; + MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); + orientation = new int[]{centerImage.getOrientation(), centerImage.getInvert()}; + boolean recycleCropped; + Bitmap croppedBitmap; + if (entry.cropState != null) { + croppedBitmap = createCroppedBitmap(bitmap, entry.cropState, orientation, true); + recycleCropped = true; + } else { + croppedBitmap = bitmap; + if (orientation[0] != 0) { + Matrix matrix = new Matrix(); + matrix.postRotate(orientation[0]); + if (orientation[1] == 1) { + matrix.postScale(-1, 1); + } else if (orientation[1] == 2) { + matrix.postScale(1, -1); + } + croppedBitmap = Bitmaps.createBitmap(croppedBitmap, 0, 0, croppedBitmap.getWidth(), croppedBitmap.getHeight(), matrix, true); + recycleCropped = true; + } else { + recycleCropped = false; + } + } + if ((currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_STICKER_MASK) && sendPhotoType == SELECT_TYPE_STICKER && !isCurrentVideo) { + if (entry.cropState != null) { + if (entry.paintPath != null) { + Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); + Bitmap croppedPaintBitmap = createCroppedBitmap(paintBitmap, entry.cropState, null, false); + if (hasAnimatedMediaEntities()) { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } else { + mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, AndroidUtilities.getPhotoSize(), true); + } + mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, thumbSize, true); + } else { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); + entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + } else if (entry.paintPath != null) { + Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); + if (hasAnimatedMediaEntities()) { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } else { + mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, croppedBitmap, paintBitmap, AndroidUtilities.getPhotoSize(), false); + } + mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, croppedBitmap, paintBitmap, thumbSize, false); + } else { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); + entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + } + if (recycleCropped && croppedBitmap != null) { + croppedBitmap.recycle(); + } + } + private void applyCurrentEditMode() { if (currentIndex < 0 || currentIndex >= imagesArrLocals.size()) { return; @@ -9698,10 +10052,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int[] orientation = null; boolean hasChanged = false; MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); - if (currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_STICKER) { - bitmap = centerImage.getBitmap(); - orientation = new int[]{centerImage.getOrientation(), centerImage.getInvert()}; - } else if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { photoCropView.makeCrop(entry); if (entry.cropState == null && currentEditMode != EDIT_MODE_CROP) { return; @@ -9734,6 +10085,34 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat stickers = photoPaintView.getMasks(); photoPaintView.onCleanupEntities(); + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + hasChanged = true; + bitmap = maskPaintView.getBitmap(); + centerImage.setImageBitmap(bitmap); + applyCurrentEditMode(bitmap); + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + if (stickerMakerView != null) { + int r = centerImage.getOrientation() - stickerMakerView.orientation; + if (r != 0) { + int w = bitmap.getWidth(), h = bitmap.getHeight(); + int rw = w, rh = h; + if (r / 90 % 2 != 0) { + rw = h; + rh = w; + } + Bitmap rotatedBitmap = Bitmap.createBitmap(rw, rh, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(rotatedBitmap); + canvas.translate(-w / 2f, -h / 2f); + canvas.rotate(r); + canvas.translate(rw / 2f, rh / 2f); + canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + stickerMakerView.updateOutlinePath(rotatedBitmap); + } else { + stickerMakerView.updateOutlinePath(bitmap); + } + } + return; } if (bitmap == null) { return; @@ -9748,49 +10127,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat entry.imagePath = null; } - if (currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_STICKER) { - if (entry.cropState != null) { - Bitmap croppedBitmap = createCroppedBitmap(bitmap, entry.cropState, orientation, true); - if (entry.paintPath != null) { - Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); - Bitmap croppedPaintBitmap = createCroppedBitmap(paintBitmap, entry.cropState, null, false); - if (!isCurrentVideo) { - if (hasAnimatedMediaEntities()) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } else { - mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, AndroidUtilities.getPhotoSize(), true); - } - } - mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, thumbSize, true); - } else { - if (!isCurrentVideo) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); - entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - } else if (entry.paintPath != null) { - Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); - if (!isCurrentVideo) { - if (hasAnimatedMediaEntities()) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } else { - mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, paintBitmap, bitmap, AndroidUtilities.getPhotoSize(), true); - } - } - mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, paintBitmap, bitmap, thumbSize, true); - } else { - if (!isCurrentVideo) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, thumbSize, thumbSize, 70, false, 101, 101); - entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - } else if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { editState.cropState = entry.cropState; editState.croppedPaintPath = entry.croppedPaintPath; editState.croppedMediaEntities = entry.croppedMediaEntities; @@ -10020,6 +10357,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (hasChanged) { entry.isPainted = true; paintItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_editMediaButton), PorterDuff.Mode.MULTIPLY)); + } else if (sendPhotoType == SELECT_TYPE_STICKER) { + entry.isPainted = true; } } @@ -10256,12 +10595,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (mode == EDIT_MODE_PAINT) { navigationBarColorTo = 0xff000000; } else if (mode == EDIT_MODE_NONE && fancyShadows && savedState == null) { - navigationBarColorTo = 0; + navigationBarColorTo = sendPhotoType == SELECT_TYPE_STICKER ? 0x66000000 : 0; } else { - navigationBarColorTo = 0x7f000000; + navigationBarColorTo = sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000; } showEditCaption(editing && savedState == null && mode == EDIT_MODE_NONE, true); - showStickerMode(mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_STICKER, true); + showStickerMode((mode == EDIT_MODE_NONE || mode == EDIT_MODE_STICKER_MASK || mode == EDIT_MODE_PAINT && stickerEmpty) && sendPhotoType == SELECT_TYPE_STICKER, true); navigationBar.setVisibility(mode != EDIT_MODE_FILTER ? View.VISIBLE : View.INVISIBLE); switchingToMode = mode; if (currentEditMode == EDIT_MODE_NONE) { @@ -10272,7 +10611,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (mode == EDIT_MODE_NONE) { Bitmap bitmap = centerImage.getBitmap(); - if (bitmap != null) { + if (photoPaintView != null) { + photoPaintView.setDrawShadow(false); + } + if (currentEditMode == EDIT_MODE_STICKER_MASK) { + animationStartTime = System.currentTimeMillis(); + animateToY = savedTy = translationY; + animateToX = savedTx = translationX; + animateToRotate = savedRotation = rotate; + animateToMirror = mirror; + animateToScale = savedScale = scale; + } else if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -10336,33 +10685,59 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat newScale = Math.min(getContainerViewWidth(0) / (float) bitmapWidth, getContainerViewHeight(0) / (float) bitmapHeight); } } - animateToScale = newScale / oldScale * scale1(); - animateToX = 0; - translationX = getLeftInset() / 2 - getRightInset() / 2; - if (sendPhotoType == SELECT_TYPE_AVATAR) { - if (currentEditMode == EDIT_MODE_FILTER) { - animateToY = dp(36); - } else if (currentEditMode == EDIT_MODE_PAINT) { - animateToY = -dp(12); - if (photoPaintView != null) { - animateToY -= photoPaintView.getAdditionalTop() / 2f; - } - } - } else { + if (currentEditMode == EDIT_MODE_STICKER_MASK) { + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + } + if (sendPhotoType == SELECT_TYPE_STICKER && (currentEditMode == EDIT_MODE_PAINT || currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_CROP)) { + animationStartTime = System.currentTimeMillis(); + animateToX = savedTx; if (currentEditMode == EDIT_MODE_CROP) { - animateToY = dp(24 + 32); - } else if (currentEditMode == EDIT_MODE_FILTER) { - animateToY = dp(93); + animateToY = savedTy + dp(24 + 32); } else if (currentEditMode == EDIT_MODE_PAINT) { - animateToY = dp(44); + animateToY = savedTy + dp(44); if (photoPaintView != null) { animateToY -= photoPaintView.getAdditionalTop() / 2f; animateToY += photoPaintView.getAdditionalBottom() / 2f; } + } else if (currentEditMode == EDIT_MODE_FILTER) { + animateToY = savedTy + dp(93); } if (isStatusBarVisible()) { animateToY -= AndroidUtilities.statusBarHeight / 2; } + animateToScale = newScale / oldScale * savedScale; + animateToRotate = savedRotation; + animateToMirror = mirror; + } else { + animateToScale = newScale / oldScale * scale1(); + animateToX = 0; + translationX = getLeftInset() / 2 - getRightInset() / 2; + if (sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_FILTER) { + animateToY = dp(36); + } else if (currentEditMode == EDIT_MODE_PAINT) { + animateToY = -dp(12); + if (photoPaintView != null) { + animateToY -= photoPaintView.getAdditionalTop() / 2f; + } + } + } else { + if (currentEditMode == EDIT_MODE_CROP) { + animateToY = dp(24 + 32); + } else if (currentEditMode == EDIT_MODE_FILTER) { + animateToY = dp(93); + } else if (currentEditMode == EDIT_MODE_PAINT) { + animateToY = dp(44); + if (photoPaintView != null) { + animateToY -= photoPaintView.getAdditionalTop() / 2f; + animateToY += photoPaintView.getAdditionalBottom() / 2f; + } + } + if (isStatusBarVisible()) { + animateToY -= AndroidUtilities.statusBarHeight / 2; + } + } } animationStartTime = System.currentTimeMillis(); zoomAnimation = true; @@ -10403,6 +10778,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animators.add(animatorX); animators.add(ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1)); photoPaintView.onAnimationStateChanged(true); + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + animators.add(ObjectAnimator.ofFloat(maskPaintView.buttonsLayout, View.TRANSLATION_Y, dp(18))); + animators.add(ObjectAnimator.ofFloat(maskPaintView.buttonsLayout, View.ALPHA, 0)); + animators.add(ObjectAnimator.ofFloat(maskPaintView.weightChooserView, View.TRANSLATION_X, dp(-18))); + animators.add(ObjectAnimator.ofFloat(maskPaintView.weightChooserView, View.ALPHA, 0)); } animators.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); imageMoveAnimation.playTogether(animators); @@ -10432,8 +10812,24 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat FileLog.e(e); } photoPaintView = null; + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + maskPaintViewShuttingDown = true; + containerView.invalidate(); + final MaskPaintView _maskPaintView = maskPaintView; + containerView.post(() -> { + _maskPaintView.shutdown(); + try { + containerView.removeView(_maskPaintView); + } catch (Exception e) { + FileLog.e(e); + } + }); + maskPaintView = null; + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); } imageMoveAnimation = null; + final int fromEditMode = currentEditMode; currentEditMode = mode; captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE); if (paintKeyboardNotifier != null) { @@ -10442,15 +10838,22 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentEditMode != EDIT_MODE_PAINT) { translateY = 0; } - switchingToMode = -1; applying = false; if (sendPhotoType == SELECT_TYPE_AVATAR) { photoCropView.setVisibility(View.VISIBLE); } - scale = animateToScale = scale1(); - animateToX = 0; - animateToY = 0; - updateMinMax(scale); + if (sendPhotoType == SELECT_TYPE_STICKER && (fromEditMode == EDIT_MODE_PAINT || fromEditMode == EDIT_MODE_FILTER || fromEditMode == EDIT_MODE_CROP || fromEditMode == EDIT_MODE_STICKER_MASK)) { + animateToX = savedTx; + animateToY = savedTy; + animateToScale = savedScale; + animateToRotate = savedRotation; + } else { + scale = animateToScale = scale1(false); + updateMinMax(scale); + animateToX = 0; + animateToY = 0; + } + switchingToMode = -1; containerView.invalidate(); if (savedState != null) { @@ -10466,6 +10869,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0)); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 1)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 1)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 1)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0)); if (sendPhotoType != SELECT_TYPE_AVATAR) { arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0)); @@ -10539,6 +10948,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 0)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 0)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0, dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0, -actionBar.getHeight())); arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); @@ -10582,6 +10997,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photosCounterView.setVisibility(View.GONE); updateActionBarTitlePadding(); } + if (sendPhotoType == SELECT_TYPE_STICKER) { + savedTy = translationY; + savedTx = translationX; + savedScale = scale; + savedRotation = rotate; + animateToRotate = 0; + } final Bitmap bitmap = centerImage.getBitmap(); if (bitmap != null || isCurrentVideo) { @@ -10725,6 +11147,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 0)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 0)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0, dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0, -actionBar.getHeight())); if (sendPhotoType == 0 || sendPhotoType == 4) { @@ -10770,6 +11198,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } Bitmap bitmap = centerImage.getBitmap(); + if (sendPhotoType == SELECT_TYPE_STICKER) { + savedTy = translationY; + savedTx = translationX; + savedScale = scale; + savedRotation = rotate; + animateToRotate = 0; + } if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -10839,6 +11274,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, stickerEmpty ? 1 : 0)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, stickerEmpty ? 1 : 0)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, -actionBar.getHeight())); arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); @@ -10866,6 +11307,49 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }); changeModeAnimation.start(); + } else if (mode == EDIT_MODE_STICKER_MASK) { + createMaskPaintView(); + + changeModeAnimation = new AnimatorSet(); + ArrayList arrayList = new ArrayList<>(); + arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); + arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 1)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 1)); + } + arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, dp(isCurrentVideo ? 154 : 96))); + arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, -actionBar.getHeight())); + arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); + if (needCaptionLayout) { + arrayList.add(ObjectAnimator.ofFloat(captionTextViewSwitcher, View.TRANSLATION_Y, dp(isCurrentVideo ? 154 : 96))); + } + if (sendPhotoType == 0 || sendPhotoType == 4) { + arrayList.add(ObjectAnimator.ofFloat(checkImageView, View.ALPHA, 1, 0)); + arrayList.add(ObjectAnimator.ofFloat(photosCounterView, View.ALPHA, 1, 0)); + } else if (sendPhotoType == SELECT_TYPE_AVATAR) { + arrayList.add(ObjectAnimator.ofFloat(photoCropView, View.ALPHA, 1, 0)); + } + if (selectedPhotosListView.getVisibility() == View.VISIBLE) { + arrayList.add(ObjectAnimator.ofFloat(selectedPhotosListView, View.ALPHA, 1, 0)); + } + if (muteItem.getTag() != null) { + arrayList.add(ObjectAnimator.ofFloat(muteItem, View.ALPHA, 1, 0)); + } + changeModeAnimation.playTogether(arrayList); + changeModeAnimation.setDuration(200); + changeModeAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + maskPaintView.init(); + currentEditMode = mode; + changeModeAnimation = null; + switchingToMode = -1; + } + }); + changeModeAnimation.start(); } if (containerView != null) { @@ -10873,6 +11357,77 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void createMaskPaintView() { + if (maskPaintView != null) { + return; + } + MediaController.CropState state; + if (sendPhotoType == SELECT_TYPE_AVATAR) { + state = new MediaController.CropState(); + state.transformRotation = cropTransform.getOrientation(); + } else { + state = editState.cropState; + } + Bitmap originalBitmap = Bitmap.createBitmap(centerImage.getBitmapWidth(), centerImage.getBitmapHeight(), Bitmap.Config.ARGB_8888); + if (stickerMakerView != null && stickerMakerView.getSourceBitmap() != null) { + Bitmap b = stickerMakerView.getSourceBitmap(); + Canvas canvas = new Canvas(originalBitmap); + canvas.translate(originalBitmap.getWidth() / 2f, originalBitmap.getHeight() / 2f); + canvas.rotate(stickerMakerView.orientation); + final float s = originalBitmap.getWidth() / (float) (stickerMakerView.orientation / 90 % 2 != 0 ? b.getHeight() : b.getWidth()); + AndroidUtilities.rectTmp.set( + -b.getWidth() / 2f * s, + -b.getHeight() / 2f * s, + b.getWidth() / 2f * s, + b.getHeight() / 2f * s + ); + canvas.drawBitmap(b, null, AndroidUtilities.rectTmp, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + } + Bitmap bitmapToEdit = Bitmap.createBitmap(centerImage.getBitmapWidth(), centerImage.getBitmapHeight(), Bitmap.Config.ARGB_8888); + if (centerImage.getBitmap() != null) { + Bitmap b = centerImage.getBitmap(); + Canvas canvas = new Canvas(bitmapToEdit); + canvas.translate(bitmapToEdit.getWidth() / 2f, bitmapToEdit.getHeight() / 2f); + canvas.rotate(centerImage.getOrientation()); + final float s = bitmapToEdit.getWidth() / (float) (centerImage.getOrientation() / 90 % 2 != 0 ? b.getHeight() : b.getWidth()); + AndroidUtilities.rectTmp.set( + -b.getWidth() / 2f * s, + -b.getHeight() / 2f * s, + b.getWidth() / 2f * s, + b.getHeight() / 2f * s + ); + canvas.drawBitmap(b, null, AndroidUtilities.rectTmp, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + } + maskPaintView = new MaskPaintView(parentActivity, currentAccount, bitmapToEdit, originalBitmap, centerImage.getOrientation(), state) { + @Override + protected void onRenderViewAlphaUpdate(ValueAnimator animation) { + super.onRenderViewAlphaUpdate(animation); + containerView.invalidate(); + } + + @Override + protected void onDrawn() { + showEditStickerMode(true, true); + } + }; + maskPaintView.cancelButton.setOnClickListener(v -> { + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + switchToEditMode(EDIT_MODE_NONE); + }); + maskPaintView.doneButton.setOnClickListener(v -> { + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + applyCurrentEditMode(); + switchToEditMode(EDIT_MODE_NONE); + }); + maskPaintView.setEraser(maskPaintViewEraser); + int index = containerView.indexOfChild(btnLayout) - 1; + if (index < 0) index = containerView.getChildCount(); + containerView.addView(maskPaintView, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + maskPaintViewShuttingDown = false; + } + private void createPaintView() { if (photoPaintView == null) { int w; @@ -10993,8 +11548,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.setOffsetTranslationX(-dp(12)); } if (photoPaintView != null) { - photoPaintView.entitiesView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); - photoPaintView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); +// photoPaintView.entitiesView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); +// photoPaintView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); } } @@ -11048,10 +11603,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat updateActionBarTitlePadding(); } showEditCaption(false, true); - showStickerMode(false, true); + showStickerMode(false, false,true); Bitmap bitmap = centerImage.getBitmap(); final float finalScale = scale; + if (sendPhotoType == SELECT_TYPE_STICKER) { + savedTy = translationY; + savedTx = translationX; + savedScale = scale; + savedRotation = rotate; + animateToRotate = 0; + } if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -11086,12 +11648,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } oldScale = Math.min(getContainerViewWidth() / (float) bitmapWidth, getContainerViewHeight() / (float) bitmapHeight); newScale = Math.min(getContainerViewWidth(3) / (float) bitmapWidth, getContainerViewHeight(3) / (float) bitmapHeight); - animateToScale = newScale / oldScale * scale1(); // * finalScale; + animateToScale = newScale / oldScale * scale1(false); // * finalScale; animateToX = getLeftInset() / 2 - getRightInset() / 2; animationStartTime = System.currentTimeMillis(); zoomAnimation = true; } + if (photoPaintView != null) { + photoPaintView.setDrawShadow(sendPhotoType == SELECT_TYPE_STICKER && (editState == null || editState.cropState == null)); + } + windowView.setClipChildren(true); navigationBar.setVisibility(View.INVISIBLE); imageMoveAnimation = new AnimatorSet(); @@ -11119,9 +11685,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (paintKeyboardNotifier != null) { paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT); } - translateY = 0; switchingToMode = -1; - animateToScale = scale = scale1(); + animateToScale = scale = scale1(false); animateToX = 0; animateToY = 0; updateMinMax(scale); @@ -11142,6 +11707,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat final float offsetY = AndroidUtilities.dpf2(24); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, show ? 1.0f : 0.0f)); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, show ? 0.0f : offsetY)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, show ? 1.0f : 0.0f)); + } + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, show ? 1.0f : 0.0f)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.ALPHA, show ? 1.0f : 0.0f)); arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, show ? 0.0f : offsetY)); if (sendPhotoType == 0 || sendPhotoType == 4) { @@ -11859,6 +12430,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (countView != null) { countView.updateShow(false, false); } + if (sendPhotoType != SELECT_TYPE_STICKER && stickerMakerView != null) { + stickerEmpty = false; + if (tuneItem != null) { + tuneItem.setAlpha(1f); + } + if (outlineBtn != null) outlineBtn.setActive(false, false); + stickerMakerView.clean(); + if (selectedEmojis != null) selectedEmojis.clear(); + } bottomLayout.setTranslationY(0); captionTextViewSwitcher.setTranslationY(0); setItemVisible(editItem, false, false); @@ -12185,7 +12765,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pickerViewSendButton.setTranslationY(0); pickerViewSendButton.setAlpha(1.0f); } - if (navigationBar != null && !fancyShadows) { + if (navigationBar != null && (!fancyShadows || sendPhotoType == SELECT_TYPE_STICKER)) { navigationBar.setVisibility(View.VISIBLE); navigationBar.setAlpha(1.0f); } @@ -12209,6 +12789,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { setImageIndex(index); } + if (tuneItem != null) { + tuneItem.setAlpha(stickerEmpty ? .4f : 1f); + } dialogPhotos = null; if (currentAnimation == null && !isEvent) { @@ -12947,12 +13530,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.hideSubItem(gallery_menu_translate); menuItem.hideSubItem(gallery_menu_hide_translation); } - fancyShadows = editing && setAvatarFor == null; + fancyShadows = editing && setAvatarFor == null || sendPhotoType == SELECT_TYPE_STICKER; actionBar.setBackgroundColor(fancyShadows || setAvatarFor != null ? 0 : Theme.ACTION_BAR_PHOTO_VIEWER_COLOR); actionBarContainer.setTextShadows(fancyShadows); - navigationBar.setVisibility(fancyShadows ? View.GONE : View.VISIBLE); + navigationBar.setVisibility(fancyShadows && sendPhotoType != SELECT_TYPE_STICKER ? View.GONE : View.VISIBLE); if (currentEditMode == EDIT_MODE_NONE) { - navigationBar.setBackgroundColor(fancyShadows ? 0 : (sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000)); + navigationBar.setBackgroundColor(fancyShadows ? (sendPhotoType == SELECT_TYPE_STICKER ? 0x66000000 : 0) : (sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000)); } if (title != null) { if (animated) { @@ -12994,7 +13577,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat message = MessageObject.replaceAnimatedEmoji(message, messageObject.messageOwner.translatedText.entities, Theme.chat_msgTextPaint.getFontMetricsInt(), false); if (MessageObject.containsUrls(message)) { try { - AndroidUtilities.addLinks((Spannable) message, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS); + AndroidUtilities.addLinksSafe((Spannable) message, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, false, true); } catch (Exception e) { FileLog.e(e); } @@ -13010,58 +13593,188 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } public TLRPC.Document replacedSticker; + public boolean stickerEmpty; + public boolean stickerEmptySent; + public Utilities.Callback2 customStickerHandler; - public void enableStickerMode(TLRPC.Document document) { + public void enableStickerMode(TLRPC.Document document, boolean empty, Utilities.Callback2 customHandler) { replacedSticker = document; + stickerEmpty = empty; + stickerEmptySent = false; + customStickerHandler = customHandler; + rotate = 0; + animateToRotate = 0; if (stickerMakerView != null) { + if (outlineBtn != null) outlineBtn.setActive(false, false); stickerMakerView.clean(); + if (selectedEmojis != null) selectedEmojis.clear(); + } + if (replacedSticker != null) { + if (selectedEmojis == null) { + selectedEmojis = new ArrayList<>(); + } else { + selectedEmojis.clear(); + } + ArrayList stickerEmojis = MessageObject.findStickerEmoticons(document, currentAccount); + if (stickerEmojis != null) { + selectedEmojis.addAll(stickerEmojis); + } } if (cutOutBtn != null) { cutOutBtn.clean(); } showStickerMode(true, false); + if (tuneItem != null) { + tuneItem.setAlpha(stickerEmpty ? .4f : 1f); + } } public void prepareSegmentImage() { if (stickerMakerView != null && sendPhotoType == SELECT_TYPE_STICKER) { - stickerMakerView.segmentImage(centerImage.getBitmap(), centerImage.getOrientation(), getContainerViewWidth(), getContainerViewHeight()); + if (stickerEmpty) { + stickerMakerView.clean(); + } else { + stickerMakerView.segmentImage(centerImage.getBitmap(), centerImage.getOrientation(), getContainerViewWidth(), getContainerViewHeight(), object -> { + try { + MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); + boolean hasFilters = !TextUtils.isEmpty(entry.filterPath); + stickerMakerView.setSegmentedState(true, object); + Bitmap segmentedImage = stickerMakerView.getSegmentedImage(centerImage.getBitmap(), hasFilters, centerImage.getOrientation()); + centerImage.setImageBitmap(segmentedImage); + cutOutBtn.setUndoCutState(true); + showStickerMode(true, true, true); + cutOutBtn.post(this::applyCurrentEditMode); + } catch (Exception e) { + FileLog.e(e); + } + }); + } } } private void showStickerMode(boolean show, boolean animated) { + showStickerMode(show, show, animated); + } + + private void showStickerMode(boolean show, boolean buttonsShow, boolean animated) { if (!animated) { stickerMakerView.animate().setListener(null).cancel(); stickerMakerView.setVisibility(show ? View.VISIBLE : View.GONE); stickerMakerView.setAlpha(pickerView.getAlpha()); stickerMakerBackgroundView.animate().setListener(null).cancel(); stickerMakerBackgroundView.setVisibility(show ? View.VISIBLE : View.GONE); - stickerMakerBackgroundView.setAlpha(show ? pickerView.getAlpha() : 0f); - cutOutBtn.animate().setListener(null).cancel(); - cutOutBtn.setVisibility(show ? View.VISIBLE : View.GONE); - cutOutBtn.setAlpha(pickerView.getAlpha()); + stickerMakerBackgroundView.setAlpha(show ? 1f : 0f); } else { - if (show && cutOutBtn.getTag() == null) { + if (show && stickerMakerView.getTag() == null) { stickerMakerView.animate().setListener(null).cancel(); - cutOutBtn.animate().setListener(null).cancel(); stickerMakerBackgroundView.animate().setListener(null).cancel(); - if (cutOutBtn.getVisibility() != View.VISIBLE) { - cutOutBtn.setVisibility(View.VISIBLE); - cutOutBtn.animate().alpha(pickerView.getAlpha()).start(); + if (stickerMakerView.getVisibility() != View.VISIBLE) { stickerMakerView.setVisibility(View.VISIBLE); - stickerMakerView.animate().alpha(pickerView.getAlpha()).start(); + stickerMakerView.animate().alpha(1f).start(); stickerMakerBackgroundView.setVisibility(View.VISIBLE); - stickerMakerBackgroundView.animate().alpha(pickerView.getAlpha()).start(); + stickerMakerBackgroundView.animate().alpha(1f).start(); } - } else if (!show && cutOutBtn.getTag() != null) { + } else if (!show && stickerMakerView.getTag() != null) { stickerMakerView.animate().setListener(null).cancel(); - cutOutBtn.animate().setListener(null).cancel(); - stickerMakerBackgroundView.animate().setListener(null).cancel(); - cutOutBtn.animate().alpha(0f).setListener(new HideViewAfterAnimation(cutOutBtn)).start(); stickerMakerView.animate().alpha(0f).setListener(new HideViewAfterAnimation(stickerMakerView)).start(); + stickerMakerBackgroundView.animate().setListener(null).cancel(); stickerMakerBackgroundView.animate().alpha(0f).setListener(new HideViewAfterAnimation(stickerMakerBackgroundView)).start(); } } - cutOutBtn.setTag(show ? 1 : null); + stickerMakerView.setTag(show ? 1 : null); + boolean buttonShow = show && !cutOutBtn.isUndoCutState() && !stickerEmpty; + if (!animated) { + cutOutBtn.animate().setListener(null).cancel(); + cutOutBtn.setVisibility(buttonShow ? View.VISIBLE : View.GONE); + cutOutBtn.setAlpha(buttonShow ? 1f : 0f); + } else { + if (buttonShow && cutOutBtn.getTag() == null) { + cutOutBtn.animate().setListener(null).cancel(); + if (cutOutBtn.getVisibility() != View.VISIBLE) { + cutOutBtn.setVisibility(View.VISIBLE); + } + cutOutBtn.animate().alpha(1f).start(); + } else if (!buttonShow && cutOutBtn.getTag() != null) { + cutOutBtn.animate().setListener(null).cancel(); + cutOutBtn.animate().alpha(0f).setListener(new HideViewAfterAnimation(cutOutBtn)).start(); + } + } + cutOutBtn.setTag(buttonShow ? 1 : null); + showEditStickerMode(show && cutOutBtn.isUndoCutState() && !stickerEmpty, animated); + + stickerMakerView.setOutlineVisible(show && cutOutBtn.isUndoCutState() && outlineBtn.isActive() && !(eraseBtn.isActive() || restoreBtn.isActive())); + boolean outlineShow = show && cutOutBtn.isUndoCutState() && !(eraseBtn.isActive() || restoreBtn.isActive()); + if (!animated) { + outlineBtn.animate().setListener(null).cancel(); + outlineBtn.setVisibility(outlineShow ? View.VISIBLE : View.GONE); + outlineBtn.setAlpha(outlineShow ? 1f : 0f); + outlineBtn.setScaleX(outlineShow ? 1f : .8f); + outlineBtn.setScaleY(outlineShow ? 1f : .8f); + } else { + if (outlineShow && outlineBtn.getTag() == null) { + outlineBtn.animate().setListener(null).cancel(); + if (outlineBtn.getVisibility() != View.VISIBLE) { + outlineBtn.setVisibility(View.VISIBLE); + } + outlineBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } else if (!outlineShow && outlineBtn.getTag() != null) { + outlineBtn.animate().setListener(null).cancel(); + outlineBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(outlineBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } + outlineBtn.setTag(outlineShow ? 1 : null); + } + + private void showEditStickerMode(boolean show, boolean animated) { + boolean showUndoBtn = show && stickerMakerView != null && (!stickerMakerView.empty || stickerMakerView.overriddenPaths() || maskPaintView != null && maskPaintView.canUndo()); + if (!animated) { + undoBtn.animate().setListener(null).cancel(); + undoBtn.setVisibility(showUndoBtn ? View.VISIBLE : View.GONE); + undoBtn.setAlpha(showUndoBtn ? 1f : 0f); + undoBtn.setScaleX(showUndoBtn ? 1f : .8f); + undoBtn.setScaleY(showUndoBtn ? 1f : .8f); + } else { + if (showUndoBtn && undoBtn.getTag() == null) { + undoBtn.animate().setListener(null).cancel(); + if (undoBtn.getVisibility() != View.VISIBLE) { + undoBtn.setVisibility(View.VISIBLE); + undoBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } else if (!showUndoBtn && undoBtn.getTag() != null) { + undoBtn.animate().setListener(null).cancel(); + undoBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(undoBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } + undoBtn.setTag(showUndoBtn ? 1 : null); + if (!animated) { + eraseBtn.animate().setListener(null).cancel(); + eraseBtn.setVisibility(show ? View.VISIBLE : View.GONE); + eraseBtn.setAlpha(show ? 1f : 0f); + eraseBtn.setScaleX(show ? 1f : .8f); + eraseBtn.setScaleY(show ? 1f : .8f); + restoreBtn.animate().setListener(null).cancel(); + restoreBtn.setVisibility(show ? View.VISIBLE : View.GONE); + restoreBtn.setAlpha(show ? 1f : 0f); + restoreBtn.setScaleX(show ? 1f : .8f); + restoreBtn.setScaleY(show ? 1f : .8f); + } else { + if (show && eraseBtn.getTag() == null) { + eraseBtn.animate().setListener(null).cancel(); + restoreBtn.animate().setListener(null).cancel(); + if (eraseBtn.getVisibility() != View.VISIBLE) { + eraseBtn.setVisibility(View.VISIBLE); + eraseBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + restoreBtn.setVisibility(View.VISIBLE); + restoreBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } else if (!show && eraseBtn.getTag() != null) { + eraseBtn.animate().setListener(null).cancel(); + eraseBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(eraseBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + restoreBtn.animate().setListener(null).cancel(); + restoreBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(restoreBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } + eraseBtn.setTag(show ? 1 : null); } private ObjectAnimator captionAnimator; @@ -13139,6 +13852,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoTimelineAnimator.start(); } } + if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != View.GONE) { + videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46))); + } videoTimelineViewContainer.setTag(show ? 1 : null); } @@ -13385,7 +14101,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } pinchStartDistance = 0; + pinchStartAngle = 0; pinchStartScale = 1; + pinchStartRotate = 0; pinchCenterX = 0; pinchCenterY = 0; pinchStartX = 0; @@ -13395,6 +14113,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat zooming = false; moving = false; paintViewTouched = 0; + maskPaintViewTouched = 0; doubleTap = false; invalidCoords = false; canDragDown = true; @@ -14526,7 +15245,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pickerViewSendButton.setLayoutParams(layoutParams2); } if (type != SELECT_TYPE_STICKER && stickerMakerView != null) { + stickerEmpty = false; + if (tuneItem != null) { + tuneItem.setAlpha(1f); + } + if (outlineBtn != null) outlineBtn.setActive(false, false); stickerMakerView.clean(); + if (selectedEmojis != null) selectedEmojis.clear(); } if (sendPhotoType != SELECT_TYPE_AVATAR && type == SELECT_TYPE_AVATAR && isVisible) { sendPhotoType = type; @@ -14565,6 +15290,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return true; } sendPhotoType = type; + if (sendPhotoType == SELECT_TYPE_STICKER) { + navigationBar.setBackgroundColor(0xFF000000); + } return openPhoto(null, fileLocation, imageLocation, null, null, null, photos, index, provider, chatActivity, 0, 0, 0, true, null, null); } @@ -15001,6 +15729,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } yPos = ((AndroidUtilities.displaySize.y + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0)) - (layoutParams.height * scale)) / 2.0f; xPos = (windowView.getMeasuredWidth() - layoutParams.width * scale) / 2.0f; + rotate = 0; + animateToRotate = 0; } int clipHorizontal = (int) Math.abs(left - object.imageReceiver.getImageX()); int clipVertical = (int) Math.abs(top - object.imageReceiver.getImageY()); @@ -15230,7 +15960,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animatorSet.playTogether( ObjectAnimator.ofFloat(containerView, View.ALPHA, 0f, 1f).setDuration(220), ObjectAnimator.ofFloat(navigationBar, View.ALPHA, 0f, 1f).setDuration(220), - a2 + a2, a3 ); animatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -15373,6 +16103,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } public void closePhoto(boolean animated, boolean fromEditMode) { + if (stickerMakerView != null) { + stickerMakerView.isThanosInProgress = false; + if (cutOutBtn.isCancelState()) { + cutOutBtn.setCutOutState(true); + showEditStickerMode(false, true); + stickerMakerView.disableClippingMode(); + containerView.invalidate(); + } + } if (!fromEditMode && currentEditMode != EDIT_MODE_NONE) { if (currentEditMode == EDIT_MODE_PAINT && photoPaintView != null) { closePaintMode(); @@ -15381,6 +16120,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentEditMode == EDIT_MODE_CROP) { cropTransform.setViewTransform(previousHasTransform, previousCropPx, previousCropPy, previousCropRotation, previousCropOrientation, previousCropScale, 1.0f, 1.0f, previousCropPw, previousCropPh, 0, 0, previousCropMirrored); } + if (currentEditMode == EDIT_MODE_STICKER_MASK) { + applyCurrentEditMode(); + } switchToEditMode(EDIT_MODE_NONE); return; } @@ -15415,6 +16157,19 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.removeView(photoPaintView.getView()); photoPaintView = null; savedState = null; + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + maskPaintViewShuttingDown = true; + if (containerView != null) { + containerView.invalidate(); + final MaskPaintView _maskPaintView = maskPaintView; + containerView.post(() -> { + _maskPaintView.shutdown(); + containerView.removeView(maskPaintView); + }); + } else { + maskPaintView.shutdown(); + } + maskPaintView = null; } currentEditMode = EDIT_MODE_NONE; captionEdit.keyboardNotifier.ignore(false); @@ -15701,6 +16456,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat invalidateBlur(); onPhotoClosed(object); MediaController.getInstance().tryResumePausedAudio(); + if (stickerEmpty && !stickerEmptySent && imagesArrLocals != null) { + for (Object obj : imagesArrLocals) { + if (obj instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry entry = (MediaController.PhotoEntry) obj; + entry.deleteAll(); + } + } + } }; animatorSet.setDuration(200); @@ -15745,6 +16508,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.setScaleX(1.0f); containerView.setScaleY(1.0f); MediaController.getInstance().tryResumePausedAudio(); + if (stickerEmpty && !stickerEmptySent && imagesArrLocals != null) { + for (Object obj : imagesArrLocals) { + if (obj instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry entry = (MediaController.PhotoEntry) obj; + entry.deleteAll(); + } + } + } }; animatorSet.setDuration(200); animatorSet.addListener(new AnimatorListenerAdapter() { @@ -16023,21 +16794,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } - private int getAdditionX() { - if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + private int getAdditionX(int mode) { + if (mode == EDIT_MODE_CROP || mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { return dp(16); - } else if (currentEditMode != EDIT_MODE_NONE && currentEditMode != EDIT_MODE_PAINT) { + } else if (mode != EDIT_MODE_NONE && mode != EDIT_MODE_STICKER_MASK && mode != EDIT_MODE_PAINT) { return dp(14); } return 0; } - private int getAdditionY() { - if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + private int getAdditionY(int mode) { + if (mode < 0) + return 0; + if (mode == EDIT_MODE_CROP || mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { return dp(16) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0); - } else if (currentEditMode == EDIT_MODE_PAINT) { + } else if (mode == EDIT_MODE_PAINT && photoPaintView != null) { return dp(8) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0) + photoPaintView.getAdditionalTop(); - } else if (currentEditMode != EDIT_MODE_NONE) { + } else if (mode != EDIT_MODE_NONE && mode != EDIT_MODE_STICKER_MASK) { return dp(14) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0); } return 0; @@ -16049,9 +16822,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private int getContainerViewWidth(int mode) { int width = containerView.getWidth(); - if (mode == 1 || mode == 0 && sendPhotoType == SELECT_TYPE_AVATAR) { + if (mode == EDIT_MODE_CROP || mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { width -= dp(32); - } else if (mode != 0 && mode != 3) { + } else if (mode != EDIT_MODE_NONE && mode != EDIT_MODE_STICKER_MASK && mode != EDIT_MODE_PAINT) { width -= dp(28); } return width; @@ -16071,7 +16844,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat height = containerView.getMeasuredHeight(); } else { height = AndroidUtilities.displaySize.y; - if (mode == EDIT_MODE_NONE && sendPhotoType != SELECT_TYPE_AVATAR && isStatusBarVisible()) { + if ((mode == EDIT_MODE_NONE || mode == EDIT_MODE_STICKER_MASK) && sendPhotoType != SELECT_TYPE_AVATAR && isStatusBarVisible()) { height += AndroidUtilities.statusBarHeight; } } @@ -16148,9 +16921,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.onTouch(event); event.recycle(); paintViewTouched = 2; + } else if (maskPaintViewTouched == 1) { + MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); + maskPaintView.onTouch(event); + event.recycle(); + maskPaintViewTouched = 2; } pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)); + pinchStartAngle = (float) Math.atan2(ev.getY(1) - ev.getY(0), ev.getX(1) - ev.getX(0)); pinchStartScale = scale; + pinchStartRotate = rotate; pinchCenterX = (ev.getX(0) + ev.getX(1)) / 2.0f; pinchCenterY = (ev.getY(0) + ev.getY(1)) / 2.0f; pinchStartX = translationX; @@ -16180,6 +16960,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat paintViewTouched = 1; } } + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + if (maskPaintViewTouched == 0) { + View v = maskPaintView; + v.getHitRect(hitRect); + if (hitRect.contains((int) ev.getX(), (int) ev.getY())) { + MotionEvent event = MotionEvent.obtain(ev); + event.offsetLocation(-v.getX(), -v.getY()); + maskPaintView.onTouch(event); + event.recycle(); + maskPaintViewTouched = 1; + } + } } else { moveStartX = ev.getX(); dragY = moveStartY = ev.getY(); @@ -16219,6 +17011,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pinchCenterX = newPinchCenterX; pinchCenterY = newPinchCenterY; } + if (sendPhotoType == SELECT_TYPE_STICKER && currentEditMode == EDIT_MODE_NONE) { + rotate = (float) ((Math.atan2(ev.getY(1) - ev.getY(0), ev.getX(1) - ev.getX(0)) - pinchStartAngle) / Math.PI * 180 + pinchStartRotate); + } scale = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)) / pinchStartDistance * pinchStartScale; translationX = (pinchCenterX - getContainerViewWidth() / 2) - ((pinchCenterX - getContainerViewWidth() / 2) - pinchStartX) * (scale / pinchStartScale); translationY = (pinchCenterY - getContainerViewHeight() / 2) - ((pinchCenterY - getContainerViewHeight() / 2) - pinchStartY) * (scale / pinchStartScale); @@ -16233,6 +17028,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.onTouch(event); event.recycle(); return true; + } else if (maskPaintViewTouched == 1 && maskPaintView != null) { + View v = maskPaintView; + MotionEvent event = MotionEvent.obtain(ev); + event.offsetLocation(-v.getX(), -v.getY()); + maskPaintView.onTouch(event); + event.recycle(); + return true; } if (velocityTracker != null) { velocityTracker.addMovement(ev); @@ -16319,20 +17121,33 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.onTouch(event); event.recycle(); } - paintViewTouched = 0; + maskPaintViewTouched = paintViewTouched = 0; + return true; + } + if (maskPaintViewTouched == 1) { + if (maskPaintView != null) { + View v = maskPaintView; + MotionEvent event = MotionEvent.obtain(ev); + event.offsetLocation(-v.getX(), -v.getY()); + maskPaintView.onTouch(event); + event.recycle(); + } + maskPaintViewTouched = paintViewTouched = 0; return true; } paintViewTouched = 0; + maskPaintViewTouched = 0; if (zooming) { invalidCoords = true; - float maxScale = sendPhotoType == SELECT_TYPE_STICKER ? 0.33f : 1f; - if (scale < maxScale) { + float maxScale = sendPhotoType == SELECT_TYPE_STICKER ? 10.0f : 3.0f; + float minScale = sendPhotoType == SELECT_TYPE_STICKER ? 0.33f : 1f; + if (scale < minScale) { + updateMinMax(minScale); + animateTo(minScale, 0, 0, true); + } else if (scale > maxScale) { + float atx = (pinchCenterX - getContainerViewWidth() / 2) - ((pinchCenterX - getContainerViewWidth() / 2) - pinchStartX) * (maxScale / pinchStartScale); + float aty = (pinchCenterY - getContainerViewHeight() / 2) - ((pinchCenterY - getContainerViewHeight() / 2) - pinchStartY) * (maxScale / pinchStartScale); updateMinMax(maxScale); - animateTo(maxScale, 0, 0, true); - } else if (scale > 3.0f) { - float atx = (pinchCenterX - getContainerViewWidth() / 2) - ((pinchCenterX - getContainerViewWidth() / 2) - pinchStartX) * (3.0f / pinchStartScale); - float aty = (pinchCenterY - getContainerViewHeight() / 2) - ((pinchCenterY - getContainerViewHeight() / 2) - pinchStartY) * (3.0f / pinchStartScale); - updateMinMax(3.0f); if (atx < minX) { atx = minX; } else if (atx > maxX) { @@ -16343,7 +17158,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (aty > maxY) { aty = maxY; } - animateTo(3.0f, atx, aty, true); + animateTo(maxScale, atx, aty, true); } else { checkMinMax(true); if (currentEditMode == EDIT_MODE_PAINT) { @@ -16473,7 +17288,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat zoomAnimation = false; containerView.invalidate(); } - + public void zoomOut() { animateTo(1f, 0, 0, false); } @@ -16699,6 +17514,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat translationX = animateToX; translationY = animateToY; scale = animateToScale; + rotate = animateToRotate; animationStartTime = 0; updateMinMax(scale); zoomAnimation = false; @@ -16894,7 +17710,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float translateX = currentTranslationX; float scaleDiff = 0; float alpha = 1; - if (!zoomAnimation && translateX > maxX && currentEditMode == EDIT_MODE_NONE && sendPhotoType != SELECT_TYPE_AVATAR) { + if (!zoomAnimation && translateX > maxX && (currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_STICKER_MASK) && sendPhotoType != SELECT_TYPE_AVATAR) { alpha = Math.min(1.0f, (translateX - maxX) / containerWidth); scaleDiff = alpha * 0.3f; alpha = 1.0f - alpha; @@ -16903,22 +17719,46 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat boolean drawTextureView = videoSizeSet && aspectRatioFrameLayout != null && aspectRatioFrameLayout.getVisibility() == View.VISIBLE; centerImageTransformLocked = false; centerImageTransform.reset(); + if (maskPaintView != null && !maskPaintViewShuttingDown && maskPaintView.getRenderView() != null) { + alpha = maskPaintView.getRenderView().getAlpha() > .99f ? 0f : 1f; + } if (centerImage.hasBitmapImage() || drawTextureView && textureUploaded) { + if (stickerMakerView != null && stickerMakerView.outlineVisible) { + boolean isCropped = false; + try { + Object object = imagesArrLocals.get(currentIndex); + MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); + isCropped = photoEntry.isCropped; + } catch (Exception e) {} + if (isCropped) { + stickerMakerView.updateOutlineBounds(false); + } else { + int stickerSize = containerWidth - dp(20); + stickerMakerView.outlineMatrix.reset(); + stickerMakerView.outlineMatrix.postTranslate(-.5f, -.5f); + stickerMakerView.outlineMatrix.postScale(stickerSize, stickerSize); + stickerMakerView.outlineMatrix.postScale(1f / currentScale, 1f / currentScale); + stickerMakerView.outlineMatrix.postTranslate(-currentTranslationX / currentScale, -currentTranslationY / currentScale); + stickerMakerView.outlineMatrix.postRotate(-currentRotation); + stickerMakerView.updateOutlineBounds(true); + } + } + canvas.save(); - canvas.translate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); - centerImageTransform.postTranslate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); + canvas.translate(containerWidth / 2f + getAdditionX(currentEditMode), containerHeight / 2f + getAdditionY(currentEditMode)); + centerImageTransform.preTranslate(containerWidth / 2f + getAdditionX(currentEditMode), containerHeight / 2f + getAdditionY(currentEditMode)); canvas.translate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); centerImageTransform.preTranslate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); canvas.scale(currentScale - scaleDiff, currentScale - scaleDiff); centerImageTransform.preScale(currentScale - scaleDiff, currentScale - scaleDiff); canvas.rotate(currentRotation); - centerImageTransform.postRotate(currentRotation); + centerImageTransform.preRotate(currentRotation); if (currentEditMode == EDIT_MODE_PAINT && photoPaintView != null) { int trueH = getContainerViewHeight(true, 0); trueH -= photoPaintView.getEmojiPadding(Math.abs(AndroidUtilities.displaySize.y + AndroidUtilities.statusBarHeight - trueH) < dp(20)); int h = getContainerViewHeight(false, 0); canvas.translate(0, (trueH - h) / 2f * (1f - photoPaintView.adjustPanLayoutHelperProgress())); - centerImageTransform.postTranslate(0, (trueH - h) / 2f * (1f - photoPaintView.adjustPanLayoutHelperProgress())); + centerImageTransform.preTranslate(0, (trueH - h) / 2f * (1f - photoPaintView.adjustPanLayoutHelperProgress())); } boolean drawCenterImage = false; @@ -16944,15 +17784,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } width *= scale; height *= scale; -// centerImageTransform.postScale(scale, scale); centerImage.setImageCoords(-width / 2, -height / 2, width, height); if (isCurrentVideo) { centerImage.draw(canvas); + centerImageTransformLocked = true; } else { drawCenterImage = true; } } - centerImageTransformLocked = true; } int bitmapWidth, originalWidth; @@ -16976,9 +17815,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT) { applyCrop = true; } else if (sendPhotoType == SELECT_TYPE_AVATAR) { - applyCrop = (switchingToMode == EDIT_MODE_NONE || currentEditMode != EDIT_MODE_PAINT && currentEditMode != EDIT_MODE_FILTER); + applyCrop = (switchingToMode == EDIT_MODE_NONE || currentEditMode != EDIT_MODE_FILTER); } else { - applyCrop = imageMoveAnimation != null && switchingToMode != -1 || currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_CROP || switchingToMode != -1; + applyCrop = imageMoveAnimation != null && switchingToMode != -1 || currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_STICKER_MASK || currentEditMode == EDIT_MODE_CROP || switchingToMode != -1; } } else { applyCrop = false; @@ -17000,7 +17839,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { cropAnimationValue = 1.0f; } else if (imageMoveAnimation != null && switchingToMode != -1) { - if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP || (currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT) && switchingToMode == -1) { + if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP) { cropAnimationValue = 1.0f; } else if (switchingToMode == EDIT_MODE_NONE) { cropAnimationValue = animationValue; @@ -17069,21 +17908,21 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } canvas.translate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); - if (!centerImageTransformLocked) centerImageTransform.postTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); + if (!centerImageTransformLocked) centerImageTransform.preTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); canvas.scale(cropScale, cropScale); - if (!centerImageTransformLocked) centerImageTransform.postScale(cropScale, cropScale); + if (!centerImageTransformLocked) centerImageTransform.preScale(cropScale, cropScale); canvas.translate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); - if (!centerImageTransformLocked) centerImageTransform.postTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); + if (!centerImageTransformLocked) centerImageTransform.preTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); float rotation = (cropTransform.getRotation() + orientation); if (rotation > 180) { rotation -= 360; } if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { canvas.rotate(rotation); - if (!centerImageTransformLocked) centerImageTransform.postRotate(rotation); + if (!centerImageTransformLocked) centerImageTransform.preRotate(rotation); } else { canvas.rotate(rotation * cropAnimationValue); - if (!centerImageTransformLocked) centerImageTransform.postRotate(rotation * cropAnimationValue); + if (!centerImageTransformLocked) centerImageTransform.preRotate(rotation * cropAnimationValue); } } else { if (videoTextureView != null) { @@ -17098,6 +17937,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (currentEditMode == EDIT_MODE_PAINT) { photoPaintView.setTransform(currentScale, currentTranslationX, currentTranslationY + (sendPhotoType == SELECT_TYPE_AVATAR ? AndroidUtilities.statusBarHeight / 2f : 0) * photoPaintView.getRenderView().getScaleX(), bitmapWidth * scaleToFitX, bitmapHeight * scaleToFitX); + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + maskPaintView.setTransform(currentScale, currentTranslationX, currentTranslationY, currentRotation, bitmapWidth * scaleToFitX, bitmapHeight * scaleToFitX); } if (drawCenterImage && !usedSurfaceView) { @@ -17127,7 +17968,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (videoTextureView instanceof VideoEditTextureView) { VideoEditTextureView videoEditTextureView = (VideoEditTextureView) videoTextureView; - videoEditTextureView.setViewRect((containerWidth - width) / 2 + getAdditionX() + translateX, (containerHeight - height) / 2 + getAdditionY() + currentTranslationY + currentPanTranslationY, width, height); + videoEditTextureView.setViewRect((containerWidth - width) / 2f + getAdditionX(currentEditMode) + translateX, (containerHeight - height) / 2f + getAdditionY(currentEditMode) + currentTranslationY + currentPanTranslationY, width, height); } if (videoSurfaceView != null && waitingForDraw == 0 && !changingTextureView && !switchingInlineMode && !pipAnimationInProgress && videoSurfaceView.getVisibility() != View.VISIBLE) { videoSurfaceView.setVisibility(View.VISIBLE); @@ -17317,6 +18158,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat drawFancyShadows(canvas); } + private Matrix m; private Path clipFancyShadows; private Paint topFancyShadowPaint, bottomFancyShadowPaint; @@ -17396,8 +18238,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat canvas.skew(0, 4 * currentMirror * (1f - currentMirror) * .25f); } if (photoViewerWebView == null || !photoViewerWebView.isLoaded()) { + if (!centerImageTransformLocked) centerImageTransform.preTranslate(centerImage.getImageX(), centerImage.getImageY()); + stickerMakerView.drawOutline(canvas, false, containerView, switchingToMode != -1); centerImage.setAlpha(alpha); centerImage.draw(canvas); + stickerMakerView.drawOutline(canvas, true, containerView, switchingToMode != -1); stickerMakerView.drawSegmentBorderPath(canvas, centerImage, centerImageTransform, containerView); centerImageTransformLocked = true; } @@ -17542,6 +18387,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return tempInt; } + private void onActionClick(boolean download) { if (currentMessageObject == null && currentBotInlineResult == null && (pageBlocksAdapter == null || currentFileNames[0] == null) && sendPhotoType != SELECT_TYPE_NO_SELECT) { return; @@ -18421,8 +19267,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (show) { if (fancyShadows) { navigationBar.setVisibility(View.VISIBLE); - navigationBar.setAlpha(0f); - navigationBar.setBackgroundColor((sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000)); + navigationBar.setAlpha(sendPhotoType == SELECT_TYPE_STICKER ? 1f : 0f); + navigationBar.setBackgroundColor((sendPhotoType == SELECT_TYPE_STICKER ? 0x66000000 : 0x7f000000)); } qualityChooseView.setTag(1); qualityChooseViewAnimation.playTogether( @@ -19024,12 +19870,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat boolean drawTextureView = videoSizeSet && aspectRatioFrameLayout != null && aspectRatioFrameLayout.getVisibility() == View.VISIBLE; if (centerImage.hasBitmapImage() || drawTextureView && textureUploaded) { canvas.save(); - canvas.translate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); + canvas.translate(containerWidth / 2 + getAdditionX(currentEditMode), containerHeight / 2 + getAdditionY(currentEditMode)); canvas.translate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); canvas.scale(currentScale - scaleDiff, currentScale - scaleDiff); canvas.rotate(currentRotation); if (allowCrossfade) { - imageBoundsMatrix.preTranslate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); + imageBoundsMatrix.preTranslate(containerWidth / 2 + getAdditionX(currentEditMode), containerHeight / 2 + getAdditionY(currentEditMode)); imageBoundsMatrix.preTranslate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); imageBoundsMatrix.preScale(currentScale - scaleDiff, currentScale - scaleDiff, 0, 0); imageBoundsMatrix.preRotate(currentRotation); @@ -19416,12 +20262,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void cancelStickerClippingMode() { if (sendPhotoType == SELECT_TYPE_STICKER && cutOutBtn.isCancelState()) { cutOutBtn.setCutOutState(true); + showEditStickerMode(true, true); stickerMakerView.disableClippingMode(); containerView.invalidate(); } } private void invalidateBlur() { + if (stickerMakerView != null && stickerMakerView.isThanosInProgress) { + return; + } if (animationInProgress != 0) { return; } @@ -19431,6 +20281,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (cutOutBtn != null) { cutOutBtn.invalidateBlur(); } + if (eraseBtn != null) { + eraseBtn.invalidateBlur(); + } + if (restoreBtn != null) { + restoreBtn.invalidateBlur(); + } + if (undoBtn != null) { + undoBtn.invalidateBlur(); + } + if (outlineBtn != null) { + outlineBtn.invalidateBlur(); + } if (videoTimelineView != null) { videoTimelineView.invalidateBlur(); } @@ -19438,4 +20300,278 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.invalidate(); } } + + private class BlurButton extends StickerCutOutBtn { + public BlurButton() { + super(stickerMakerView, activityContext, resourcesProvider, blurManager); + } + + private final Path path = new Path(); + private boolean active; + private final AnimatedFloat activeFloat = new AnimatedFloat(this, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + path.rewind(); + path.addRoundRect(bounds, dp(rad), dp(rad), Path.Direction.CW); + canvas.clipPath(path); + canvas.translate(-getX(), -getY()); + if (this == eraseBtn || this == restoreBtn) { + canvas.translate(-btnLayout.getX(), -btnLayout.getY()); + } + drawCaptionBlur(canvas, blurDrawer, 0xFF2b2b2b, 0x33000000, false, true, false); + float active = activeFloat.set(this.active); + if (active > 0) { + canvas.drawColor(Theme.multAlpha(Color.WHITE, active)); + } + setTextColor(ColorUtils.blendARGB(0xFFFFFFFF, 0xFF000000, active)); + canvas.restore(); + super.onDraw(canvas); + } + + @Override + public void onDrawForeground(Canvas canvas) { + canvas.save(); + canvas.clipPath(path); + super.onDrawForeground(canvas); + canvas.restore(); + } + + public void setActive(boolean active, boolean animated) { + this.active = active; + if (!animated) { + activeFloat.set(active, true); + } + invalidate(); + } + + public boolean isActive() { + return active; + } + } + + private void applyTransformToOutline(Canvas canvas) { + float currentTranslationY; + float currentTranslationX; + float currentScale; + float currentRotation; + float currentMirror; + if (imageMoveAnimation != null) { + currentMirror = lerp(mirror, animateToMirror, animationValue); + currentScale = lerp(scale, animateToScale, animationValue); + currentRotation = lerp(rotate, animateToRotate, animationValue); + currentTranslationY = lerp(translationY, animateToY, animationValue); + currentTranslationX = lerp(translationX, animateToX, animationValue); + } else { + currentScale = scale; + currentMirror = mirror; + currentRotation = rotate; + currentTranslationY = translationY; + currentTranslationX = translationX; + if (animationStartTime != 0) { + currentTranslationX = animateToX; + currentTranslationY = animateToY; + currentScale = animateToScale; + } + } + + int containerWidth = getContainerViewWidth(); + int containerHeight = getContainerViewHeight(); + + canvas.translate(getAdditionX(currentEditMode), getAdditionY(currentEditMode)); + canvas.translate(currentTranslationX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); + canvas.scale(currentScale, currentScale); + canvas.rotate(currentRotation); + + int bitmapWidth, originalWidth; + int bitmapHeight, originalHeight; + originalWidth = bitmapWidth = centerImage.getBitmapWidth(); + originalHeight = bitmapHeight = centerImage.getBitmapHeight(); + + float scale = Math.min(containerWidth / (float) originalWidth, containerHeight / (float) originalHeight); + + float scaleToFitX = 1.0f; + int rotatedWidth = originalWidth; + int rotatedHeight = originalHeight; + int orientation = cropTransform.getOrientation(); + if (orientation == 90 || orientation == 270) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + + temp = rotatedWidth; + rotatedWidth = rotatedHeight; + rotatedHeight = temp; + } + float cropAnimationValue = 1.0f; + float cropPw = cropTransform.getCropPw(); + float cropPh = cropTransform.getCropPh(); + bitmapWidth *= cropPw + (1.0f - cropPw) * (1.0f - cropAnimationValue); + bitmapHeight *= cropPh + (1.0f - cropPh) * (1.0f - cropAnimationValue); + scaleToFitX = containerWidth / (float) bitmapWidth; + if (scaleToFitX * bitmapHeight > containerHeight) { + scaleToFitX = containerHeight / (float) bitmapHeight; + } + if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != 1 || switchingToMode == EDIT_MODE_NONE) && editState.cropState != null) { + float startW = bitmapWidth * scaleToFitX; + float startH = bitmapHeight * scaleToFitX; + float originalScaleToFitX = containerWidth / (float) originalWidth; + if (originalScaleToFitX * originalHeight > containerHeight) { + originalScaleToFitX = containerHeight / (float) originalHeight; + } + float finalW = originalWidth * originalScaleToFitX / (currentScale); + float finalH = originalHeight * originalScaleToFitX / (currentScale); + + float w = startW + (finalW - startW) * (1.0f - cropAnimationValue); + float h = startH + (finalH - startH) * (1.0f - cropAnimationValue); + + canvas.clipRect(-w / 2, -h / 2, w / 2, h / 2); + } + if (sendPhotoType == SELECT_TYPE_AVATAR || cropTransform.hasViewTransform()) { + float cropScale; + if (videoTextureView != null) { + videoTextureView.setScaleX(editState.cropState != null && editState.cropState.mirrored ? -1.0f : 1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(videoTextureView.getScaleX()); + } + } + cropScale = editState.cropState != null ? editState.cropState.cropScale : 1.0f; + float trueScale = 1.0f + (cropScale - 1.0f) * (1.0f - cropAnimationValue); + cropScale *= scaleToFitX / scale / trueScale; + + canvas.translate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); + canvas.scale(cropScale, cropScale); + canvas.translate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); + float rotation = (cropTransform.getRotation() + orientation); + if (rotation > 180) { + rotation -= 360; + } + canvas.rotate(rotation); + } + + boolean mirror = false; + if (!imagesArrLocals.isEmpty()) { + mirror = editState.cropState != null && editState.cropState.mirrored; + } + if (mirror) { + canvas.scale(-1, 1); + } + if (currentMirror > 0) { + canvas.scale(1 - currentMirror * 2, 1f); + canvas.skew(0, 4 * currentMirror * (1f - currentMirror) * .25f); + } + } + + private void applyTransformToMatrix(Matrix matrix) { + float currentTranslationY; + float currentTranslationX; + float currentScale; + float currentRotation; + float currentMirror; + if (imageMoveAnimation != null) { + currentMirror = lerp(mirror, animateToMirror, animationValue); + currentScale = lerp(scale, animateToScale, animationValue); + currentRotation = lerp(rotate, animateToRotate, animationValue); + currentTranslationY = lerp(translationY, animateToY, animationValue); + currentTranslationX = lerp(translationX, animateToX, animationValue); + } else { + currentScale = scale; + currentMirror = mirror; + currentRotation = rotate; + currentTranslationY = translationY; + currentTranslationX = translationX; + if (animationStartTime != 0) { + currentTranslationX = animateToX; + currentTranslationY = animateToY; + currentScale = animateToScale; + } + } + + int containerWidth = getContainerViewWidth(); + int containerHeight = getContainerViewHeight(); + +// matrix.postTranslate(containerWidth / 2f + getAdditionX(currentEditMode), containerHeight / 2f + getAdditionY(currentEditMode)); + matrix.preTranslate(currentTranslationX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); + matrix.preScale(currentScale, currentScale); + matrix.preRotate(currentRotation); + + int bitmapWidth, originalWidth; + int bitmapHeight, originalHeight; + originalWidth = bitmapWidth = centerImage.getBitmapWidth(); + originalHeight = bitmapHeight = centerImage.getBitmapHeight(); + + float scale = Math.min(containerWidth / (float) originalWidth, containerHeight / (float) originalHeight); + + float scaleToFitX = 1.0f; + int rotatedWidth = originalWidth; + int rotatedHeight = originalHeight; + int orientation = cropTransform.getOrientation(); + if (orientation == 90 || orientation == 270) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + + temp = rotatedWidth; + rotatedWidth = rotatedHeight; + rotatedHeight = temp; + } + float cropAnimationValue = 1.0f; + float cropPw = cropTransform.getCropPw(); + float cropPh = cropTransform.getCropPh(); + bitmapWidth *= cropPw + (1.0f - cropPw) * (1.0f - cropAnimationValue); + bitmapHeight *= cropPh + (1.0f - cropPh) * (1.0f - cropAnimationValue); + scaleToFitX = containerWidth / (float) bitmapWidth; + if (scaleToFitX * bitmapHeight > containerHeight) { + scaleToFitX = containerHeight / (float) bitmapHeight; + } +// if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != 1 || switchingToMode == EDIT_MODE_NONE) && editState.cropState != null) { +// float startW = bitmapWidth * scaleToFitX; +// float startH = bitmapHeight * scaleToFitX; +// float originalScaleToFitX = containerWidth / (float) originalWidth; +// if (originalScaleToFitX * originalHeight > containerHeight) { +// originalScaleToFitX = containerHeight / (float) originalHeight; +// } +// float finalW = originalWidth * originalScaleToFitX / (currentScale); +// float finalH = originalHeight * originalScaleToFitX / (currentScale); +// +// float w = startW + (finalW - startW) * (1.0f - cropAnimationValue); +// float h = startH + (finalH - startH) * (1.0f - cropAnimationValue); +// +// canvas.clipRect(-w / 2, -h / 2, w / 2, h / 2); +// } + if (sendPhotoType == SELECT_TYPE_AVATAR || cropTransform.hasViewTransform()) { + float cropScale; + if (videoTextureView != null) { + videoTextureView.setScaleX(editState.cropState != null && editState.cropState.mirrored ? -1.0f : 1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(videoTextureView.getScaleX()); + } + } + cropScale = editState.cropState != null ? editState.cropState.cropScale : 1.0f; + float trueScale = 1.0f + (cropScale - 1.0f) * (1.0f - cropAnimationValue); + cropScale *= scaleToFitX / scale / trueScale; + + matrix.preTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); + matrix.preScale(cropScale, cropScale); + matrix.preTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); + float rotation = (cropTransform.getRotation() + orientation); + if (rotation > 180) { + rotation -= 360; + } + matrix.preRotate(rotation); + } + + boolean mirror = false; + if (!imagesArrLocals.isEmpty()) { + mirror = editState.cropState != null && editState.cropState.mirrored; + } + if (mirror) { + matrix.preScale(-1, 1); + } + if (currentMirror > 0) { + matrix.preScale(1 - currentMirror * 2, 1f); + matrix.preSkew(0, 4 * currentMirror * (1f - currentMirror) * .25f); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java index 86ca52fde..d78850955 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java @@ -1,5 +1,10 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -7,8 +12,11 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.Editable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.ImageSpan; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; @@ -18,16 +26,24 @@ import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.SerializedData; 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.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; @@ -40,12 +56,18 @@ import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.ChatActivityEnterViewAnimatedIconView; import org.telegram.ui.Components.ChatAttachAlertPollLayout; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.EmojiView; import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SizeNotifierFrameLayout; +import org.telegram.ui.Components.SuggestEmojiView; +import org.telegram.ui.Stories.recorder.KeyboardNotifier; import java.util.ArrayList; import java.util.Arrays; @@ -56,18 +78,20 @@ import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -public class PollCreateActivity extends BaseFragment { +public class PollCreateActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate { private ActionBarMenuItem doneItem; private ListAdapter listAdapter; private RecyclerListView listView; + private RecyclerView.LayoutManager layoutManager; + private SizeNotifierFrameLayout sizeNotifierFrameLayout; private ChatActivity parentFragment; private HintView hintView; - private String[] answers = new String[10]; + private CharSequence[] answers = new CharSequence[10]; private boolean[] answersChecks = new boolean[10]; private int answersCount = 1; - private String questionString; + private CharSequence questionString; private CharSequence solutionString; private boolean anonymousPoll = true; private boolean multipleChoise; @@ -75,6 +99,21 @@ public class PollCreateActivity extends BaseFragment { private boolean hintShowed; private int quizOnly; + public boolean emojiViewVisible, emojiViewWasVisible; + + private SuggestEmojiView suggestEmojiPanel; + private EmojiView emojiView; + private KeyboardNotifier keyboardNotifier; + private boolean waitingForKeyboardOpen; + private boolean destroyed; + private int emojiPadding; + private int keyboardHeight, keyboardHeightLand; + private boolean keyboardVisible, isAnimatePopupClosing; + private int lastSizeChangeValue1; + private boolean lastSizeChangeValue2; + private PollEditTextCell currentCell; + private boolean isPremium; + private PollCreateActivityDelegate delegate; private int requestFieldFocusAtPosition = -1; @@ -151,9 +190,25 @@ public class PollCreateActivity extends BaseFragment { } } + private Runnable openKeyboardRunnable = new Runnable() { + @Override + public void run() { + if (currentCell != null) { + EditTextBoldCursor editText = currentCell.getEditField(); + if (!destroyed && editText != null && waitingForKeyboardOpen && !keyboardVisible && !AndroidUtilities.usingHardwareInput && !AndroidUtilities.isInMultiwindow && AndroidUtilities.isTablet()) { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + } + }; + public PollCreateActivity(ChatActivity chatActivity, Boolean quiz) { super(); parentFragment = chatActivity; + isPremium = AccountInstance.getInstance(currentAccount).getUserConfig().isPremium(); if (quiz != null) { quizPoll = quiz; quizOnly = quizPoll ? 1 : 2; @@ -199,19 +254,44 @@ public class PollCreateActivity extends BaseFragment { } return; } + CharSequence questionText = ChatAttachAlertPollLayout.getFixedString(questionString); + CharSequence[] questionCharSequence = new CharSequence[]{ questionText }; + ArrayList questionEntities = MediaDataController.getInstance(currentAccount).getEntities(questionCharSequence, true); + questionText = questionCharSequence[0]; + for (int a = 0, N = questionEntities.size(); a < N; a++) { + TLRPC.MessageEntity entity = questionEntities.get(a); + if (entity.offset + entity.length > questionText.length()) { + entity.length = questionText.length() - entity.offset; + } + } + TLRPC.TL_messageMediaPoll poll = new TLRPC.TL_messageMediaPoll(); poll.poll = new TLRPC.TL_poll(); poll.poll.multiple_choice = multipleChoise; poll.poll.quiz = quizPoll; poll.poll.public_voters = !anonymousPoll; - poll.poll.question = ChatAttachAlertPollLayout.getFixedString(questionString).toString(); + poll.poll.question = new TLRPC.TL_textWithEntities(); + poll.poll.question.text = questionText.toString(); + poll.poll.question.entities = questionEntities; SerializedData serializedData = new SerializedData(10); for (int a = 0; a < answers.length; a++) { if (TextUtils.isEmpty(ChatAttachAlertPollLayout.getFixedString(answers[a]))) { continue; } - TLRPC.TL_pollAnswer answer = new TLRPC.TL_pollAnswer(); - answer.text = ChatAttachAlertPollLayout.getFixedString(answers[a]).toString(); + CharSequence answerText = ChatAttachAlertPollLayout.getFixedString(answers[a]); + CharSequence[] answerCharSequence = new CharSequence[]{ answerText }; + ArrayList answerEntities = MediaDataController.getInstance(currentAccount).getEntities(answerCharSequence, true); + answerText = answerCharSequence[0]; + for (int b = 0, N = answerEntities.size(); b < N; b++) { + TLRPC.MessageEntity entity = answerEntities.get(b); + if (entity.offset + entity.length > answerText.length()) { + entity.length = answerText.length() - entity.offset; + } + } + TLRPC.PollAnswer answer = new TLRPC.TL_pollAnswer(); + answer.text = new TLRPC.TL_textWithEntities(); + answer.text.text = answerText.toString(); + answer.text.entities = answerEntities; answer.option = new byte[1]; answer.option[0] = (byte) (48 + poll.poll.answers.size()); poll.poll.answers.add(answer); @@ -252,7 +332,131 @@ public class PollCreateActivity extends BaseFragment { listAdapter = new ListAdapter(context); - fragmentView = new FrameLayout(context); + sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + + private boolean ignoreLayout; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + heightSize -= getPaddingTop(); + + measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); + + int keyboardSize = measureKeyboardHeight(); + if (keyboardSize > AndroidUtilities.dp(20) && !emojiViewVisible) { + ignoreLayout = true; + hideEmojiView(); + ignoreLayout = false; + } + + int keyboardPad = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? getEmojiPadding() : 0; + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE || child == actionBar) { + continue; + } + if (emojiView != null && emojiView == child) { + if (AndroidUtilities.isInMultiwindow || AndroidUtilities.isTablet()) { + if (AndroidUtilities.isTablet()) { + child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(AndroidUtilities.isTablet() ? 200 : 320), heightSize - AndroidUtilities.statusBarHeight + getPaddingTop()), MeasureSpec.EXACTLY)); + } else { + child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize - AndroidUtilities.statusBarHeight + getPaddingTop(), MeasureSpec.EXACTLY)); + } + } else { + child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, MeasureSpec.EXACTLY)); + } + } else if (listView == child) { + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(heightSize - keyboardPad, MeasureSpec.EXACTLY)); + } else { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int count = getChildCount(); + + int keyboardSize = measureKeyboardHeight(); + int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? getEmojiPadding() : 0; + setBottomClip(paddingBottom); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + final LayoutParams lp = (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 = (r - l - width) / 2 + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + childLeft = r - width - lp.rightMargin; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin; + } + + switch (verticalGravity) { + case Gravity.TOP: + childTop = lp.topMargin + getPaddingTop(); + break; + case Gravity.CENTER_VERTICAL: + childTop = ((b - paddingBottom) - t - height) / 2 + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = ((b - paddingBottom) - t) - height - lp.bottomMargin; + break; + default: + childTop = lp.topMargin; + } + + if (emojiView != null && emojiView == child) { + if (AndroidUtilities.isTablet()) { + childTop = getMeasuredHeight() - child.getMeasuredHeight(); + } else { + childTop = getMeasuredHeight() + keyboardSize - child.getMeasuredHeight(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + sizeNotifierFrameLayout.setDelegate(this); + + fragmentView = sizeNotifierFrameLayout; fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); FrameLayout frameLayout = (FrameLayout) fragmentView; @@ -273,7 +477,8 @@ public class PollCreateActivity extends BaseFragment { }; listView.setVerticalScrollBarEnabled(false); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); + listView.setLayoutManager(layoutManager); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new TouchHelperCallback()); itemTouchHelper.attachToRecyclerView(listView); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); @@ -285,6 +490,9 @@ public class PollCreateActivity extends BaseFragment { TextCheckCell cell = (TextCheckCell) view; boolean checked; boolean wasChecksBefore = quizPoll; + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } if (position == anonymousRow) { checked = anonymousPoll = !anonymousPoll; } else if (position == multipleRow) { @@ -365,6 +573,27 @@ public class PollCreateActivity extends BaseFragment { if (dy != 0 && hintView != null) { hintView.hide(); } + if (suggestEmojiPanel != null && suggestEmojiPanel.isShown()) { + SuggestEmojiView.AnchorViewDelegate emojiDelegate = suggestEmojiPanel.getDelegate(); + if (emojiDelegate instanceof PollEditTextCell) { + PollEditTextCell cell = (PollEditTextCell) emojiDelegate; + RecyclerView.ViewHolder holder = listView.findContainingViewHolder(cell); + if (holder != null) { + if (suggestEmojiPanel.getDirection() == SuggestEmojiView.DIRECTION_TO_BOTTOM) { + suggestEmojiPanel.setTranslationY(holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight()); + } else { + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + if (!layoutManager.isViewPartiallyVisible(holder.itemView, true, true)) { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } } }); @@ -374,11 +603,32 @@ public class PollCreateActivity extends BaseFragment { hintView.setVisibility(View.INVISIBLE); frameLayout.addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); + if (isPremium) { + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + suggestEmojiPanel = new SuggestEmojiView(context, currentAccount, null, resourceProvider); + suggestEmojiPanel.forbidCopy(); + suggestEmojiPanel.forbidSetAsStatus(); + suggestEmojiPanel.setHorizontalPadding(AndroidUtilities.dp(24)); + frameLayout.addView(suggestEmojiPanel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 160, Gravity.LEFT | Gravity.TOP)); + } + keyboardNotifier = new KeyboardNotifier(sizeNotifierFrameLayout, null); + checkDoneButton(); return fragmentView; } + @Override + public void onPause() { + super.onPause(); + if (isPremium) { + hideEmojiPopup(false); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + } + } + @Override public void onResume() { super.onResume(); @@ -388,6 +638,32 @@ public class PollCreateActivity extends BaseFragment { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + destroyed = true; + if (isPremium) { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + if (emojiView != null) { + sizeNotifierFrameLayout.removeView(emojiView); + } + } + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + if (emojiView != null) { + emojiView.invalidateViews(); + } + if (currentCell != null) { + int color = currentCell.getEditField().getCurrentTextColor(); + currentCell.getEditField().setTextColor(0xffffffff); + currentCell.getEditField().setTextColor(color); + } + } + } + private void showQuizHint() { int count = listView.getChildCount(); for (int a = answerStartRow; a < answerStartRow + answersCount; a++) { @@ -482,6 +758,10 @@ public class PollCreateActivity extends BaseFragment { @Override public boolean onBackPressed() { + if (emojiViewVisible) { + hideEmojiPopup(true); + return true; + } return checkDiscard(); } @@ -542,6 +822,11 @@ public class PollCreateActivity extends BaseFragment { } private void addNewField() { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + resetSuggestEmojiPanel(); answersChecks[answersCount] = false; answersCount++; if (answersCount == answers.length) { @@ -553,6 +838,341 @@ public class PollCreateActivity extends BaseFragment { listAdapter.notifyItemChanged(answerSectionRow); } + private void updateSuggestEmojiPanelDelegate(RecyclerView.ViewHolder holder) { + if (suggestEmojiPanel != null ) { + suggestEmojiPanel.forceClose(); + if (suggestEmojiPanel != null && holder != null && holder.itemView instanceof PollEditTextCell && suggestEmojiPanel.getDelegate() != holder.itemView) { + suggestEmojiPanel.setDelegate((PollEditTextCell) holder.itemView); + } + } + } + + private void resetSuggestEmojiPanel() { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.setDelegate(null); + suggestEmojiPanel.forceClose(); + } + } + + @Override + public void onSizeChanged(int height, boolean isWidthGreater) { + if (!isPremium) { + return; + } + if (height > dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + if (isWidthGreater) { + keyboardHeightLand = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height_land3", keyboardHeightLand).commit(); + } else { + keyboardHeight = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height", keyboardHeight).commit(); + } + } + + if (emojiViewVisible) { + int newHeight = (isWidthGreater ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) emojiView.getLayoutParams(); + if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { + layoutParams.width = AndroidUtilities.displaySize.x; + layoutParams.height = newHeight; + emojiView.setLayoutParams(layoutParams); + emojiPadding = layoutParams.height; + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + } + } + + if (lastSizeChangeValue1 == height && lastSizeChangeValue2 == isWidthGreater) { + return; + } + lastSizeChangeValue1 = height; + lastSizeChangeValue2 = isWidthGreater; + + boolean oldValue = keyboardVisible; + if (currentCell != null) { + final EditTextBoldCursor editText = currentCell.getEditField(); + keyboardVisible = editText.isFocused() && keyboardNotifier.keyboardVisible() && height > 0; + } else { + keyboardVisible = false; + } + + if (keyboardVisible && emojiViewVisible) { + showEmojiPopup(0); + } + + if (emojiPadding != 0 && !keyboardVisible && keyboardVisible != oldValue && !emojiViewVisible) { + emojiPadding = 0; + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + } + + if (keyboardVisible && waitingForKeyboardOpen) { + waitingForKeyboardOpen = false; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + } + } + + public boolean isWaitingForKeyboardOpen() { + return waitingForKeyboardOpen; + } + + private void onEmojiClicked(PollEditTextCell cell) { + this.currentCell = cell; + if (emojiViewVisible) { + openKeyboardInternal(); + } else { + showEmojiPopup(1); + } + } + + private void openKeyboardInternal() { + keyboardNotifier.awaitKeyboard(); + final EditTextBoldCursor editText = currentCell.getEditField(); + AndroidUtilities.showKeyboard(editText); + showEmojiPopup(AndroidUtilities.usingHardwareInput ? 0 : 2); + + if (!AndroidUtilities.usingHardwareInput && !keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + waitingForKeyboardOpen = true; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + + private void showEmojiPopup(int show) { + if (!isPremium) { + return; + } + + if (show == 1) { + boolean emojiWasVisible = emojiView != null && emojiView.getVisibility() == View.VISIBLE; + createEmojiView(); + + emojiView.setVisibility(View.VISIBLE); + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = true; + View currentView = emojiView; + + if (keyboardHeight <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeight = dp(150); + } else { + keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", dp(200)); + } + } + if (keyboardHeightLand <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeightLand = dp(150); + } else { + keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", dp(200)); + } + } + int currentHeight = (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) currentView.getLayoutParams(); + layoutParams.height = currentHeight; + currentView.setLayoutParams(layoutParams); + if (!AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() && currentCell != null) { + AndroidUtilities.hideKeyboard(currentCell.getEditField()); + } + + emojiPadding = currentHeight; + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.KEYBOARD, true); + } + if (!emojiWasVisible && !keyboardVisible) { + ValueAnimator animator = ValueAnimator.ofFloat(emojiPadding, 0); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + emojiView.setTranslationY(0); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } + } else { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, true); + } + if (emojiView != null) { + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = false; + if (AndroidUtilities.usingHardwareInput || AndroidUtilities.isInMultiwindow) { + emojiView.setVisibility(View.GONE); + } + } + if (show == 0) { + emojiPadding = 0; + } + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + } + } + + private void hideEmojiPopup(boolean byBackButton) { + if (!isPremium) { + return; + } + if (emojiViewVisible) { + showEmojiPopup(0); + } + if (byBackButton) { + if (emojiView != null && emojiView.getVisibility() == View.VISIBLE) { + int height = emojiView.getMeasuredHeight(); + ValueAnimator animator = ValueAnimator.ofFloat(0, height); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + isAnimatePopupClosing = true; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimatePopupClosing = false; + emojiView.setTranslationY(0); + hideEmojiView(); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } else { + hideEmojiView(); + } + } + } + + public void hideEmojiView() { + if (!emojiViewVisible && emojiView != null && emojiView.getVisibility() != View.GONE) { + if (currentCell != null) { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } + } + emojiView.setVisibility(View.GONE); + } + int wasEmojiPadding = emojiPadding; + emojiPadding = 0; + if (wasEmojiPadding != emojiPadding) { + keyboardNotifier.fire(); + } + } + + public boolean isAnimatePopupClosing() { + return isAnimatePopupClosing; + } + + public boolean isPopupShowing() { + return emojiViewVisible; + } + + public boolean isPopupVisible() { + return emojiView != null && emojiView.getVisibility() == View.VISIBLE; + } + + public int getEmojiPadding() { + return emojiPadding; + } + + private void createEmojiView() { + if (emojiView != null && emojiView.currentAccount != UserConfig.selectedAccount) { + sizeNotifierFrameLayout.removeView(emojiView); + emojiView = null; + } + if (emojiView != null) { + return; + } + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourceProvider, false); + emojiView.fixBottomTabContainerTranslation = false; + emojiView.allowEmojisForNonPremium(false); + emojiView.setVisibility(View.GONE); + if (AndroidUtilities.isTablet()) { + emojiView.setForseMultiwindowLayout(true); + } + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { + @Override + public boolean onBackspace() { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return false; + } + editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + return true; + } + + @Override + public void onEmojiSelected(String symbol) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, editText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + editText.setText(editText.getText().insert(i, localCharSequence)); + int j = i + localCharSequence.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onCustomEmojiSelected(long documentId, TLRPC.Document document, String emoticon, boolean isRecent) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + SpannableString spannable = new SpannableString(emoticon); + AnimatedEmojiSpan span; + if (document != null) { + span = new AnimatedEmojiSpan(document, editText.getPaint().getFontMetricsInt()); + } else { + span = new AnimatedEmojiSpan(documentId, editText.getPaint().getFontMetricsInt()); + } + span.cacheType = emojiView.emojiCacheType; + spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editText.setText(editText.getText().insert(i, spannable)); + int j = i + spannable.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onClearEmojiRecent() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourceProvider); + builder.setTitle(LocaleController.getString("ClearRecentEmojiTitle", R.string.ClearRecentEmojiTitle)); + builder.setMessage(LocaleController.getString("ClearRecentEmojiText", R.string.ClearRecentEmojiText)); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.show(); + } + }); + sizeNotifierFrameLayout.addView(emojiView); + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -665,10 +1285,17 @@ public class PollCreateActivity extends BaseFragment { @Override public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() == 4) { + if (holder.getItemViewType() == 4 || holder.getItemViewType() == 5) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; EditTextBoldCursor editText = editTextCell.getTextView(); if (editText.isFocused()) { + if (isPremium) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + hideEmojiPopup(true); + } + currentCell = null; editText.clearFocus(); AndroidUtilities.hideKeyboard(editText); } @@ -700,7 +1327,38 @@ public class PollCreateActivity extends BaseFragment { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 4: { - PollEditTextCell cell = new PollEditTextCell(mContext, null); + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { + @Override + protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionMode) { + if (editText.isFocused() && editText.hasSelection()) { + Menu menu = actionMode.getMenu(); + if (menu.findItem(android.R.id.copy) == null) { + return; + } + ChatActivity.fillActionModeMenu(menu, parentFragment.getCurrentEncryptedChat(), false); + } + } + + @Override + protected void onFieldTouchUp(EditTextBoldCursor editText) { + super.onFieldTouchUp(editText); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } + }; cell.createErrorTextView(); cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); cell.addTextWatcher(new TextWatcher() { @@ -719,8 +1377,22 @@ public class PollCreateActivity extends BaseFragment { if (cell.getTag() != null) { return; } - questionString = s.toString(); RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } + questionString = s; if (holder != null) { setTextLeft(holder.itemView, questionRow); } @@ -735,7 +1407,7 @@ public class PollCreateActivity extends BaseFragment { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 7: { - PollEditTextCell cell = new PollEditTextCell(mContext, true, null) { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { @Override protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionMode) { if (editText.isFocused() && editText.hasSelection()) { @@ -746,6 +1418,26 @@ public class PollCreateActivity extends BaseFragment { ChatActivity.fillActionModeMenu(menu, parentFragment.getCurrentEncryptedChat(), false); } } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } + + @Override + protected void onFieldTouchUp(EditTextBoldCursor editText) { + super.onFieldTouchUp(editText); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } }; cell.createErrorTextView(); cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -765,8 +1457,22 @@ public class PollCreateActivity extends BaseFragment { if (cell.getTag() != null) { return; } + RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } solutionString = s; - RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(solutionRow); if (holder != null) { setTextLeft(holder.itemView, solutionRow); } @@ -777,7 +1483,7 @@ public class PollCreateActivity extends BaseFragment { break; } default: { - PollEditTextCell cell = new PollEditTextCell(mContext, v -> { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, v -> { if (v.getTag() != null) { return; } @@ -802,16 +1508,54 @@ public class PollCreateActivity extends BaseFragment { if (holder != null && holder.itemView instanceof PollEditTextCell) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; editTextCell.getTextView().requestFocus(); + if (isPremium) { + if (emojiViewVisible) { + currentCell = editTextCell; + editTextCell.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.KEYBOARD, false); + } else { + editTextCell.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + } + } } else if (editText.isFocused()) { AndroidUtilities.hideKeyboard(editText); + if (isPremium) { + hideEmojiPopup(false); + } + } + if (isPremium) { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); } editText.clearFocus(); checkDoneButton(); updateRows(); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + suggestEmojiPanel.setDelegate(null); + } listAdapter.notifyItemChanged(answerSectionRow); } } }) { + + @Override + protected void onFieldTouchUp(EditTextBoldCursor editText) { + super.onFieldTouchUp(editText); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } + @Override protected boolean drawDivider() { RecyclerView.ViewHolder holder = listView.findContainingViewHolder(this); @@ -866,6 +1610,11 @@ public class PollCreateActivity extends BaseFragment { } return false; } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } }; cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); cell.addTextWatcher(new TextWatcher() { @@ -888,7 +1637,25 @@ public class PollCreateActivity extends BaseFragment { if (index < 0 || index >= answers.length) { return; } - answers[index] = s.toString(); + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + float y = holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight(); + if (y > 0) { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_BOTTOM); + suggestEmojiPanel.setTranslationY(y); + } else { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.fireUpdate(); + } + + answers[index] = s; setTextLeft(cell, index); checkDoneButton(); } @@ -966,7 +1733,7 @@ public class PollCreateActivity extends BaseFragment { if (idx1 < 0 || idx2 < 0 || idx1 >= answersCount || idx2 >= answersCount) { return; } - String from = answers[idx1]; + CharSequence from = answers[idx1]; answers[idx1] = answers[idx2]; answers[idx2] = from; boolean temp = answersChecks[idx1]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java index e3134d73a..29cd81c3a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java @@ -1,6 +1,7 @@ package org.telegram.ui; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -84,9 +85,11 @@ import org.telegram.ui.Business.QuickRepliesController; import org.telegram.ui.Business.TimezonesController; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.FillLastLinearLayoutManager; @@ -143,6 +146,9 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification int statusRow; int privacyRow; int lastPaddingRow; + int showAdsHeaderRow; + int showAdsRow; + int showAdsInfoRow; Drawable shadowDrawable; private FrameLayout buttonContainer; private View buttonDivider; @@ -214,6 +220,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification private PremiumButtonView premiumButtonView; float totalProgress; private final int type; + private boolean whiteBackground; private String source; private boolean selectAnnualByDefault; @@ -406,6 +413,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification public PremiumPreviewFragment(int type, String source) { super(); this.type = type; + whiteBackground = !Theme.isCurrentThemeDark() && type == FEATURES_BUSINESS; this.source = source; } @@ -502,7 +510,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification float listX = backgroundView.getX() + backgroundView.tierListView.getX(), listY = backgroundView.getY() + backgroundView.tierListView.getY(); AndroidUtilities.rectTmp.set(listX, listY, listX + backgroundView.tierListView.getWidth(), listY + backgroundView.tierListView.getHeight()); - if ((AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || listInterceptedTouch) && !listView.scrollingByUser) { + if (progressToFull < 1.0f && (AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || listInterceptedTouch) && !listView.scrollingByUser) { ev.offsetLocation(-listX, -listY); if (ev.getAction() == MotionEvent.ACTION_DOWN) { listInterceptedTouch = true; @@ -555,6 +563,8 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification measureGradient(w, h); } + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + @Override protected void dispatchDraw(Canvas canvas) { if (!isDialogVisible) { @@ -627,9 +637,18 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification invalidate(); } gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -getMeasuredWidth() * 0.1f * progress, 0); - canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + dp(20), gradientTools.paint); + if (whiteBackground) { + backgroundPaint.setColor(ColorUtils.blendARGB(getThemedColor(Theme.key_windowBackgroundGray), getThemedColor(Theme.key_windowBackgroundWhite), progressToFull)); + canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + dp(20), backgroundPaint); + } else { + canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + dp(20), gradientTools.paint); + } super.dispatchDraw(canvas); + + if (parentLayout != null && whiteBackground) { + parentLayout.drawHeaderShadow(canvas, (int) (0xFF * progressToFull), actionBar.getBottom()); + } } @Override @@ -697,20 +716,54 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification particlesView = new StarParticlesView(context); particlesView.setClipWithGradient(); if (type == FEATURES_BUSINESS) { -// particlesView.doNotFling = true; - particlesView.drawable.isCircle = true; - particlesView.drawable.centerOffsetY = dp(28); - particlesView.drawable.minLifeTime = 2000; - particlesView.drawable.randLifeTime = 3000; - particlesView.drawable.size1 = 16; - particlesView.drawable.useRotate = false; - particlesView.drawable.type = PREMIUM_FEATURE_BUSINESS; + if (whiteBackground) { + particlesView.drawable.useGradient = true; + particlesView.drawable.useBlur = false; + particlesView.drawable.checkBounds = true; + particlesView.drawable.isCircle = true; + particlesView.drawable.centerOffsetY = dp(-14); + particlesView.drawable.minLifeTime = 2000; + particlesView.drawable.randLifeTime = 3000; + particlesView.drawable.size1 = 16; + particlesView.drawable.useRotate = false; + particlesView.drawable.type = PremiumPreviewFragment.PREMIUM_FEATURE_BUSINESS; + particlesView.drawable.colorKey = Theme.key_premiumGradient2; + } else { + particlesView.drawable.isCircle = true; + particlesView.drawable.centerOffsetY = dp(28); + particlesView.drawable.minLifeTime = 2000; + particlesView.drawable.randLifeTime = 3000; + particlesView.drawable.size1 = 16; + particlesView.drawable.useRotate = false; + particlesView.drawable.type = PREMIUM_FEATURE_BUSINESS; + } } backgroundView.imageView.setStarParticlesView(particlesView); contentView.addView(particlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); contentView.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); listView.setOnItemClickListener((view, position) -> { + if (position == showAdsRow) { + TLRPC.UserFull userFull = getMessagesController().getUserFull(getUserConfig().getClientUserId()); + if (userFull == null) return; + + TextCell cell = (TextCell) view; + cell.setChecked(!cell.isChecked()); + userFull.sponsored_enabled = cell.isChecked(); + + TLRPC.TL_account_toggleSponsoredMessages req = new TLRPC.TL_account_toggleSponsoredMessages(); + req.enabled = userFull.sponsored_enabled; + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (!(res instanceof TLRPC.TL_boolTrue)) { + BulletinFactory.of(PremiumPreviewFragment.this).createErrorBulletin(getString(R.string.UnknownError)).show(); + } + })); + + getMessagesStorage().updateUserInfo(userFull, false); + return; + } if (view instanceof PremiumFeatureCell) { PremiumFeatureCell cell = (PremiumFeatureCell) view; @@ -818,28 +871,28 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification public static void fillPremiumFeaturesList(ArrayList premiumFeatures, int currentAccount, boolean all) { MessagesController messagesController = MessagesController.getInstance(currentAccount); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LIMITS, R.drawable.msg_premium_limits, LocaleController.getString("PremiumPreviewLimits", R.string.PremiumPreviewLimits), LocaleController.formatString("PremiumPreviewLimitsDescription", R.string.PremiumPreviewLimitsDescription, + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LIMITS, R.drawable.msg_premium_limits, getString("PremiumPreviewLimits", R.string.PremiumPreviewLimits), LocaleController.formatString("PremiumPreviewLimitsDescription", R.string.PremiumPreviewLimitsDescription, messagesController.channelsLimitPremium, messagesController.dialogFiltersLimitPremium, messagesController.dialogFiltersPinnedLimitPremium, messagesController.publicLinksLimitPremium, 4))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.msg_filled_stories, LocaleController.getString(R.string.PremiumPreviewStories), LocaleController.formatString(R.string.PremiumPreviewStoriesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_UPLOAD_LIMIT, R.drawable.msg_premium_uploads, LocaleController.getString("PremiumPreviewUploads", R.string.PremiumPreviewUploads), LocaleController.getString("PremiumPreviewUploadsDescription", R.string.PremiumPreviewUploadsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_DOWNLOAD_SPEED, R.drawable.msg_premium_speed, LocaleController.getString("PremiumPreviewDownloadSpeed", R.string.PremiumPreviewDownloadSpeed), LocaleController.getString("PremiumPreviewDownloadSpeedDescription", R.string.PremiumPreviewDownloadSpeedDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_VOICE_TO_TEXT, R.drawable.msg_premium_voice, LocaleController.getString("PremiumPreviewVoiceToText", R.string.PremiumPreviewVoiceToText), LocaleController.getString("PremiumPreviewVoiceToTextDescription", R.string.PremiumPreviewVoiceToTextDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADS, R.drawable.msg_premium_ads, LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds), LocaleController.getString("PremiumPreviewNoAdsDescription", R.string.PremiumPreviewNoAdsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, LocaleController.getString(R.string.PremiumPreviewReactions2), LocaleController.getString(R.string.PremiumPreviewReactions2Description))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, LocaleController.getString(R.string.PremiumPreviewStickers), LocaleController.getString(R.string.PremiumPreviewStickersDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_EMOJI, R.drawable.msg_premium_emoji, LocaleController.getString(R.string.PremiumPreviewEmoji), LocaleController.getString(R.string.PremiumPreviewEmojiDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.menu_premium_tools, LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, LocaleController.getString(R.string.PremiumPreviewProfileBadge), LocaleController.getString(R.string.PremiumPreviewProfileBadgeDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, LocaleController.getString(R.string.PremiumPreviewAnimatedProfiles), LocaleController.getString(R.string.PremiumPreviewAnimatedProfilesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_SAVED_TAGS, R.drawable.premium_tags, LocaleController.getString(R.string.PremiumPreviewTags2), LocaleController.getString(R.string.PremiumPreviewTagsDescription2))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, LocaleController.getString(R.string.PremiumPreviewAppIcon), LocaleController.getString(R.string.PremiumPreviewAppIconDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.premium_status, LocaleController.getString(R.string.PremiumPreviewEmojiStatus), LocaleController.getString(R.string.PremiumPreviewEmojiStatusDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_TRANSLATIONS, R.drawable.msg_premium_translate, LocaleController.getString(R.string.PremiumPreviewTranslations), LocaleController.getString(R.string.PremiumPreviewTranslationsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, LocaleController.getString(R.string.PremiumPreviewWallpaper), LocaleController.getString(R.string.PremiumPreviewWallpaperDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, LocaleController.getString(R.string.PremiumPreviewProfileColor), LocaleController.getString(R.string.PremiumPreviewProfileColorDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LAST_SEEN, R.drawable.menu_premium_seen, LocaleController.getString(R.string.PremiumPreviewLastSeen), LocaleController.getString(R.string.PremiumPreviewLastSeenDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_MESSAGE_PRIVACY, R.drawable.menu_premium_privacy, LocaleController.getString(R.string.PremiumPreviewMessagePrivacy), LocaleController.getString(R.string.PremiumPreviewMessagePrivacyDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS, R.drawable.filled_premium_business, applyNewSpan(LocaleController.getString(R.string.TelegramBusiness)), LocaleController.getString(R.string.PremiumPreviewBusinessDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.msg_filled_stories, getString(R.string.PremiumPreviewStories), LocaleController.formatString(R.string.PremiumPreviewStoriesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_UPLOAD_LIMIT, R.drawable.msg_premium_uploads, getString("PremiumPreviewUploads", R.string.PremiumPreviewUploads), getString("PremiumPreviewUploadsDescription", R.string.PremiumPreviewUploadsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_DOWNLOAD_SPEED, R.drawable.msg_premium_speed, getString("PremiumPreviewDownloadSpeed", R.string.PremiumPreviewDownloadSpeed), getString("PremiumPreviewDownloadSpeedDescription", R.string.PremiumPreviewDownloadSpeedDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_VOICE_TO_TEXT, R.drawable.msg_premium_voice, getString("PremiumPreviewVoiceToText", R.string.PremiumPreviewVoiceToText), getString("PremiumPreviewVoiceToTextDescription", R.string.PremiumPreviewVoiceToTextDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADS, R.drawable.msg_premium_ads, getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds), getString("PremiumPreviewNoAdsDescription", R.string.PremiumPreviewNoAdsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, getString(R.string.PremiumPreviewReactions2), getString(R.string.PremiumPreviewReactions2Description))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, getString(R.string.PremiumPreviewStickers), getString(R.string.PremiumPreviewStickersDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_EMOJI, R.drawable.msg_premium_emoji, getString(R.string.PremiumPreviewEmoji), getString(R.string.PremiumPreviewEmojiDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.menu_premium_tools, getString(R.string.PremiumPreviewAdvancedChatManagement), getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, getString(R.string.PremiumPreviewProfileBadge), getString(R.string.PremiumPreviewProfileBadgeDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, getString(R.string.PremiumPreviewAnimatedProfiles), getString(R.string.PremiumPreviewAnimatedProfilesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_SAVED_TAGS, R.drawable.premium_tags, getString(R.string.PremiumPreviewTags2), getString(R.string.PremiumPreviewTagsDescription2))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, getString(R.string.PremiumPreviewAppIcon), getString(R.string.PremiumPreviewAppIconDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.premium_status, getString(R.string.PremiumPreviewEmojiStatus), getString(R.string.PremiumPreviewEmojiStatusDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_TRANSLATIONS, R.drawable.msg_premium_translate, getString(R.string.PremiumPreviewTranslations), getString(R.string.PremiumPreviewTranslationsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, getString(R.string.PremiumPreviewWallpaper), getString(R.string.PremiumPreviewWallpaperDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, getString(R.string.PremiumPreviewProfileColor), getString(R.string.PremiumPreviewProfileColorDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LAST_SEEN, R.drawable.menu_premium_seen, getString(R.string.PremiumPreviewLastSeen), getString(R.string.PremiumPreviewLastSeenDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_MESSAGE_PRIVACY, R.drawable.menu_premium_privacy, getString(R.string.PremiumPreviewMessagePrivacy), getString(R.string.PremiumPreviewMessagePrivacyDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS, R.drawable.filled_premium_business, applyNewSpan(getString(R.string.TelegramBusiness)), getString(R.string.PremiumPreviewBusinessDescription))); if (messagesController.premiumFeaturesTypesToPosition.size() > 0) { for (int i = 0; i < premiumFeatures.size(); i++) { @@ -861,18 +914,18 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification MessagesController messagesController = MessagesController.getInstance(currentAccount); if (!additional) { - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_LOCATION, R.drawable.filled_location, LocaleController.getString(R.string.PremiumBusinessLocation), LocaleController.getString(R.string.PremiumBusinessLocationDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_OPENING_HOURS, R.drawable.filled_premium_hours, LocaleController.getString(R.string.PremiumBusinessOpeningHours), LocaleController.getString(R.string.PremiumBusinessOpeningHoursDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_QUICK_REPLIES, R.drawable.filled_open_message, LocaleController.getString(R.string.PremiumBusinessQuickReplies), LocaleController.getString(R.string.PremiumBusinessQuickRepliesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_GREETING_MESSAGES, R.drawable.premium_status, LocaleController.getString(R.string.PremiumBusinessGreetingMessages), LocaleController.getString(R.string.PremiumBusinessGreetingMessagesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_AWAY_MESSAGES, R.drawable.filled_premium_away, LocaleController.getString(R.string.PremiumBusinessAwayMessages), LocaleController.getString(R.string.PremiumBusinessAwayMessagesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHATBOTS, R.drawable.filled_premium_bots, applyNewSpan(LocaleController.getString(R.string.PremiumBusinessChatbots2)), LocaleController.getString(R.string.PremiumBusinessChatbotsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHAT_LINKS, R.drawable.filled_premium_chatlink, applyNewSpan(LocaleController.getString(R.string.PremiumBusinessChatLinks)), LocaleController.getString(R.string.PremiumBusinessChatLinksDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_INTRO, R.drawable.filled_premium_intro, applyNewSpan(LocaleController.getString(R.string.PremiumBusinessIntro)), LocaleController.getString(R.string.PremiumBusinessIntroDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_LOCATION, R.drawable.filled_location, getString(R.string.PremiumBusinessLocation), getString(R.string.PremiumBusinessLocationDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_OPENING_HOURS, R.drawable.filled_premium_hours, getString(R.string.PremiumBusinessOpeningHours), getString(R.string.PremiumBusinessOpeningHoursDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_QUICK_REPLIES, R.drawable.filled_open_message, getString(R.string.PremiumBusinessQuickReplies), getString(R.string.PremiumBusinessQuickRepliesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_GREETING_MESSAGES, R.drawable.premium_status, getString(R.string.PremiumBusinessGreetingMessages), getString(R.string.PremiumBusinessGreetingMessagesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_AWAY_MESSAGES, R.drawable.filled_premium_away, getString(R.string.PremiumBusinessAwayMessages), getString(R.string.PremiumBusinessAwayMessagesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHATBOTS, R.drawable.filled_premium_bots, applyNewSpan(getString(R.string.PremiumBusinessChatbots2)), getString(R.string.PremiumBusinessChatbotsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHAT_LINKS, R.drawable.filled_premium_chatlink, applyNewSpan(getString(R.string.PremiumBusinessChatLinks)), getString(R.string.PremiumBusinessChatLinksDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_INTRO, R.drawable.filled_premium_intro, applyNewSpan(getString(R.string.PremiumBusinessIntro)), getString(R.string.PremiumBusinessIntroDescription))); } else { - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.filled_premium_status2, LocaleController.getString(R.string.PremiumPreviewBusinessEmojiStatus), LocaleController.getString(R.string.PremiumPreviewBusinessEmojiStatusDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_FOLDER_TAGS, R.drawable.premium_tags, LocaleController.getString(R.string.PremiumPreviewFolderTags), LocaleController.getString(R.string.PremiumPreviewFolderTagsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.filled_premium_camera, LocaleController.getString(R.string.PremiumPreviewBusinessStories), LocaleController.getString(R.string.PremiumPreviewBusinessStoriesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.filled_premium_status2, getString(R.string.PremiumPreviewBusinessEmojiStatus), getString(R.string.PremiumPreviewBusinessEmojiStatusDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_FOLDER_TAGS, R.drawable.premium_tags, getString(R.string.PremiumPreviewFolderTags), getString(R.string.PremiumPreviewFolderTagsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.filled_premium_camera, getString(R.string.PremiumPreviewBusinessStories), getString(R.string.PremiumPreviewBusinessStoriesDescription))); } if (messagesController.businessFeaturesTypesToPosition.size() > 0) { @@ -904,12 +957,19 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification if (contentView.getMeasuredWidth() == 0 || contentView.getMeasuredHeight() == 0 || backgroundView == null || backgroundView.imageView == null) { return; } - gradientTools.gradientMatrix(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), 0, 0); - gradientCanvas.save(); - gradientCanvas.scale(100f / contentView.getMeasuredWidth(), 100f / contentView.getMeasuredHeight()); - gradientCanvas.drawRect(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), gradientTools.paint); - gradientCanvas.restore(); - backgroundView.imageView.setBackgroundBitmap(gradientTextureBitmap); + if (whiteBackground) { + Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.drawColor(ColorUtils.blendARGB(getThemedColor(Theme.key_premiumGradient2), getThemedColor(Theme.key_dialogBackground), 0.5f)); + backgroundView.imageView.setBackgroundBitmap(bitmap); + } else { + gradientTools.gradientMatrix(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), 0, 0); + gradientCanvas.save(); + gradientCanvas.scale(100f / contentView.getMeasuredWidth(), 100f / contentView.getMeasuredHeight()); + gradientCanvas.drawRect(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), gradientTools.paint); + gradientCanvas.restore(); + backgroundView.imageView.setBackgroundBitmap(gradientTextureBitmap); + } } private void checkButtonDivider() { @@ -1084,9 +1144,10 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification public static String getPremiumButtonText(int currentAccount, SubscriptionTier tier) { if (BuildVars.IS_BILLING_UNAVAILABLE) { - return LocaleController.getString(R.string.SubscribeToPremiumNotAvailable); + return getString(R.string.SubscribeToPremiumNotAvailable); } + int stringResId = R.string.SubscribeToPremium; if (tier == null) { if (BuildVars.useInvoiceBilling()) { TLRPC.TL_help_premiumPromo premiumPromo = MediaDataController.getInstance(currentAccount).getPremiumPromo(); @@ -1102,20 +1163,25 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification } if (selectedOption == null) { - return LocaleController.getString(R.string.SubscribeToPremiumNoPrice); + return getString(R.string.SubscribeToPremiumNoPrice); } final String price; if (selectedOption.months == 12) { - price = BillingController.getInstance().formatCurrency(selectedOption.amount / 12, selectedOption.currency); + if (MessagesController.getInstance(currentAccount).showAnnualPerMonth) { + price = BillingController.getInstance().formatCurrency(selectedOption.amount / 12, selectedOption.currency); + } else { + stringResId = R.string.SubscribeToPremiumPerYear; + price = BillingController.getInstance().formatCurrency(selectedOption.amount, selectedOption.currency); + } } else { price = BillingController.getInstance().formatCurrency(selectedOption.amount, selectedOption.currency); } - return LocaleController.formatString(R.string.SubscribeToPremium, price); + return LocaleController.formatString(stringResId, price); } - return LocaleController.getString(R.string.SubscribeToPremiumNoPrice); + return getString(R.string.SubscribeToPremiumNoPrice); } String price = null; @@ -1127,7 +1193,12 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification if (phase.getBillingPeriod().equals("P1M")) { // Once per month price = phase.getFormattedPrice(); } else if (phase.getBillingPeriod().equals("P1Y")) { // Once per year - price = BillingController.getInstance().formatCurrency(phase.getPriceAmountMicros() / 12L, phase.getPriceCurrencyCode(), 6); + if (MessagesController.getInstance(currentAccount).showAnnualPerMonth) { + price = BillingController.getInstance().formatCurrency(phase.getPriceAmountMicros() / 12L, phase.getPriceCurrencyCode(), 6); + } else { + stringResId = R.string.SubscribeToPremiumPerYear; + price = BillingController.getInstance().formatCurrency(phase.getPriceAmountMicros(), phase.getPriceCurrencyCode(), 6); + } break; } } @@ -1135,13 +1206,13 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification } if (price == null) { - return LocaleController.getString(R.string.Loading); + return getString(R.string.Loading); } - return LocaleController.formatString(R.string.SubscribeToPremium, price); + return LocaleController.formatString(stringResId, price); } else { if (!BuildVars.useInvoiceBilling() && tier.getOfferDetails() == null) { - return LocaleController.getString(R.string.Loading); + return getString(R.string.Loading); } final boolean isPremium = UserConfig.getInstance(currentAccount).isPremium(); final boolean isYearTier = tier.getMonths() == 12; @@ -1150,8 +1221,18 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification if (isPremium) { resId = isYearTier ? R.string.UpgradePremiumPerYear : R.string.UpgradePremiumPerMonth; } else { - price = tier.getFormattedPricePerMonth(); - resId = R.string.SubscribeToPremium; + if (isYearTier) { + if (MessagesController.getInstance(currentAccount).showAnnualPerMonth) { + resId = R.string.SubscribeToPremium; + price = tier.getFormattedPricePerMonth(); + } else { + resId = R.string.SubscribeToPremiumPerYear; + price = tier.getFormattedPrice(); + } + } else { + resId = R.string.SubscribeToPremium; + price = tier.getFormattedPricePerMonth(); + } } return LocaleController.formatString(resId, price); } @@ -1182,6 +1263,9 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification moreHeaderRow = -1; moreFeaturesStartRow = -1; moreFeaturesEndRow = -1; + showAdsHeaderRow = -1; + showAdsRow = -1; + showAdsInfoRow = -1; paddingRow = rowCount++; featuresStartRow = rowCount; @@ -1197,6 +1281,12 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification statusRow = rowCount++; lastPaddingRow = rowCount++; + if (type == FEATURES_BUSINESS && getUserConfig().isPremium()) { + showAdsHeaderRow = rowCount++; + showAdsRow = rowCount++; + showAdsInfoRow = rowCount++; + } + AndroidUtilities.updateViewVisibilityAnimated(buttonContainer, !getUserConfig().isPremium() || currentSubscriptionTier != null && currentSubscriptionTier.getMonths() < subscriptionTiers.get(selectedTierIndex).getMonths() && !forcePremium, 1f, false); int buttonHeight = buttonContainer.getVisibility() == View.VISIBLE ? dp(64) : 0; @@ -1263,7 +1353,8 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification TYPE_HELP_US = 4, TYPE_SHADOW = 5, TYPE_BOTTOM_PADDING = 6, - TYPE_HEADER = 7; + TYPE_HEADER = 7, + TYPE_CHECK = 8; @NonNull @Override @@ -1325,6 +1416,9 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification case TYPE_HEADER: view = new HeaderCell(context); break; + case TYPE_CHECK: + view = new TextCell(context, 23, false, true, resourceProvider); + break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); @@ -1347,7 +1441,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification privacyCell.setText(""); privacyCell.setFixedSize(12); - } else if (position == statusRow || position == privacyRow) { + } else if (position == statusRow || position == privacyRow || position == showAdsInfoRow) { TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; Drawable shadowDrawable = Theme.getThemedDrawable(privacyCell.getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow)); @@ -1357,8 +1451,12 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification privacyCell.setBackground(combinedDrawable); privacyCell.setFixedSize(0); - if (position == statusRow && type == FEATURES_BUSINESS) { - privacyCell.setText(LocaleController.getString(R.string.PremiumPreviewMoreBusinessFeaturesInfo)); + if (position == showAdsInfoRow) { + privacyCell.setText(AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.ShowAdsInfo), () -> { + showDialog(new RevenueSharingAdsInfoBottomSheet(PremiumPreviewFragment.this, getContext(), getResourceProvider())); + }), true)); + } else if (position == statusRow && type == FEATURES_BUSINESS) { + privacyCell.setText(getString(R.string.PremiumPreviewMoreBusinessFeaturesInfo)); } else if (position == statusRow) { TLRPC.TL_help_premiumPromo premiumPromo = getMediaDataController().getPremiumPromo(); if (premiumPromo == null) { @@ -1414,7 +1512,12 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification privacyCell.setText(spannableString); } } else if (position == moreHeaderRow) { - ((HeaderCell) holder.itemView).setText(LocaleController.getString(R.string.PremiumPreviewMoreBusinessFeatures)); + ((HeaderCell) holder.itemView).setText(getString(R.string.PremiumPreviewMoreBusinessFeatures)); + } else if (position == showAdsHeaderRow) { + ((HeaderCell) holder.itemView).setText(getString(R.string.ShowAdsTitle)); + } else if (position == showAdsRow) { + TLRPC.UserFull userFull = getMessagesController().getUserFull(getUserConfig().getClientUserId()); + ((TextCell) holder.itemView).setTextAndCheck(getString(R.string.ShowAds), userFull == null || userFull.sponsored_enabled, false); } } @@ -1431,19 +1534,21 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return TYPE_FEATURE; } else if (position == helpUsRow) { return TYPE_HELP_US; - } else if (position == sectionRow || position == statusRow || position == privacyRow) { + } else if (position == sectionRow || position == statusRow || position == privacyRow || position == showAdsInfoRow) { return TYPE_SHADOW; } else if (position == lastPaddingRow) { return TYPE_BOTTOM_PADDING; - } else if (position == moreHeaderRow) { + } else if (position == moreHeaderRow || position == showAdsHeaderRow) { return TYPE_HEADER; + } else if (position == showAdsRow) { + return TYPE_CHECK; } return TYPE_PADDING; } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { - return holder.getItemViewType() == TYPE_FEATURE; + return holder.getItemViewType() == TYPE_FEATURE || holder.getItemViewType() == TYPE_CHECK; } } @@ -1479,7 +1584,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification imageFrameLayout = new FrameLayout(context); final int sz = type == FEATURES_BUSINESS ? 175 : 190; addView(imageFrameLayout, LayoutHelper.createLinear(sz, sz, Gravity.CENTER_HORIZONTAL)); - imageView = new GLIconTextureView(context, type == FEATURES_BUSINESS ? GLIconRenderer.BUSINESS_STYLE : GLIconRenderer.FRAGMENT_STYLE, type == FEATURES_BUSINESS ? Icon3D.TYPE_COIN : Icon3D.TYPE_STAR) { + imageView = new GLIconTextureView(context, whiteBackground ? GLIconRenderer.DIALOG_STYLE : type == FEATURES_BUSINESS ? GLIconRenderer.BUSINESS_STYLE : GLIconRenderer.FRAGMENT_STYLE, type == FEATURES_BUSINESS ? Icon3D.TYPE_COIN : Icon3D.TYPE_STAR) { @Override public void onLongPress() { super.onLongPress(); @@ -1507,7 +1612,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 22); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleView.setGravity(Gravity.CENTER_HORIZONTAL); addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_HORIZONTAL, 16, type == FEATURES_BUSINESS ? 8 : 20, 16, 0)); @@ -1522,18 +1627,21 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification { paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + if (whiteBackground) { + paint.setShadowLayer(dp(2), 0, dp(.66f), 0x30000000); + } } private Path path = new Path(); @Override - public void draw(Canvas c) { + public void dispatchDraw(Canvas c) { path.rewind(); AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); path.addRoundRect(AndroidUtilities.rectTmp, dp(12), dp(12), Path.Direction.CW); c.drawPath(path, paint); c.save(); c.clipPath(path); - super.draw(c); + super.dispatchDraw(c); c.restore(); } @@ -1542,6 +1650,22 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification super.onSizeChanged(w, h, oldw, oldh); measureGradient(w, h); } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (progressToFull >= 1.0f) { + return false; + } + return super.onInterceptTouchEvent(e); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent e) { + if (progressToFull >= 1.0f) { + return false; + } + return super.dispatchTouchEvent(e); + } }; tierListView.setOverScrollMode(OVER_SCROLL_NEVER); tierListView.setLayoutManager(new LinearLayoutManager(context)); @@ -1657,7 +1781,9 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification path.addRoundRect(AndroidUtilities.rectTmp, radii, Path.Direction.CW); canvas.clipPath(path); }); - addView(tierListView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 12, 16, 12, 0)); + setClipChildren(false); + setClipToPadding(false); + addView(tierListView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 12, 16, 12, 4)); updatePremiumTiers(); updateText(); @@ -1755,11 +1881,11 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification private boolean tierListViewVisible; public void updateText() { if (type == FEATURES_PREMIUM) { - titleView.setText(LocaleController.getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramPremium)); - subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramPremiumSubscribedSubtitle : R.string.TelegramPremiumSubtitle))); + titleView.setText(getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramPremium)); + subtitleView.setText(AndroidUtilities.replaceTags(getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramPremiumSubscribedSubtitle : R.string.TelegramPremiumSubtitle))); } else if (type == FEATURES_BUSINESS) { - titleView.setText(LocaleController.getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramBusiness)); - subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramBusinessSubscribedSubtitleTemp : R.string.TelegramBusinessSubtitleTemp))); + titleView.setText(getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramBusiness)); + subtitleView.setText(AndroidUtilities.replaceTags(getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramBusinessSubscribedSubtitleTemp : R.string.TelegramBusinessSubtitleTemp))); } subtitleView.getLayoutParams().width = Math.min(AndroidUtilities.displaySize.x - dp(42), HintView2.cutInFancyHalf(subtitleView.getText(), subtitleView.getPaint())); boolean tierNotVisible = forcePremium || BuildVars.IS_BILLING_UNAVAILABLE || IS_PREMIUM_TIERS_UNAVAILABLE || subscriptionTiers.size() <= 1; @@ -1821,7 +1947,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return; } if (!BuildVars.useInvoiceBilling() && (!BillingController.getInstance().isReady() || subscriptionTiers.isEmpty() || selectedTierIndex >= subscriptionTiers.size() || subscriptionTiers.get(selectedTierIndex).googlePlayProductDetails == null)) { - premiumButtonView.setButton(LocaleController.getString(R.string.Loading), v -> {}, animated); + premiumButtonView.setButton(getString(R.string.Loading), v -> {}, animated); premiumButtonView.setFlickerDisabled(true); return; } @@ -1843,7 +1969,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification @Override public boolean isLightStatusBar() { - return false; + return whiteBackground; } @Override @@ -1877,7 +2003,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification return SimpleThemeDescription.createThemeDescriptions(this::updateColors, Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4, Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4, - Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStartGradient1, Theme.key_premiumStartGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 + Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStarGradient1, Theme.key_premiumStarGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 ); } @@ -1885,14 +2011,19 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification if (backgroundView == null || actionBar == null) { return; } - actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), false); - actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), true); + actionBar.setItemsColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay), false); + actionBar.setItemsColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay), true); actionBar.setItemsBackgroundColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), 60), false); particlesView.drawable.updateColors(); if (backgroundView != null) { - backgroundView.titleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); - backgroundView.subtitleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); + backgroundView.titleView.setTextColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay)); + backgroundView.subtitleView.setTextColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay)); if (backgroundView.imageView != null && backgroundView.imageView.mRenderer != null) { + if (whiteBackground) { +// backgroundView.imageView.mRenderer.forceNight = true; + backgroundView.imageView.mRenderer.colorKey1 = Theme.key_premiumCoinGradient1; + backgroundView.imageView.mRenderer.colorKey2 = Theme.key_premiumCoinGradient2; + } backgroundView.imageView.mRenderer.updateColors(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 1166dfc2f..4b27791fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -11,7 +11,9 @@ package org.telegram.ui; import static androidx.core.view.ViewCompat.TYPE_TOUCH; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.ContactsController.PRIVACY_RULES_TYPE_ADDED_BY_PHONE; +import static org.telegram.messenger.LocaleController.formatPluralString; import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; import android.Manifest; import android.animation.Animator; @@ -68,7 +70,9 @@ import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.ForegroundColorSpan; +import android.util.Log; import android.util.Property; +import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Display; @@ -115,6 +119,7 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.AuthTokensHelper; import org.telegram.messenger.BillingController; import org.telegram.messenger.BirthdayController; import org.telegram.messenger.BuildVars; @@ -153,6 +158,7 @@ import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_fragment; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -169,7 +175,6 @@ import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Business.OpeningHoursActivity; import org.telegram.ui.Business.ProfileHoursCell; import org.telegram.ui.Business.ProfileLocationCell; -import org.telegram.ui.Business.TimezonesController; import org.telegram.ui.Cells.AboutLinkCell; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.DividerCell; @@ -181,7 +186,6 @@ import org.telegram.ui.Cells.ProfileChannelCell; import org.telegram.ui.Cells.SettingsSearchCell; import org.telegram.ui.Cells.SettingsSuggestionCell; import org.telegram.ui.Cells.ShadowSectionCell; -import org.telegram.ui.Cells.ShareDialogCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextDetailCell; @@ -192,6 +196,7 @@ import org.telegram.ui.Components.AnimatedColor; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.Components.AutoDeletePopupWrapper; @@ -257,6 +262,7 @@ import org.telegram.ui.Stories.ProfileStoriesView; import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; import org.telegram.ui.Stories.StoryViewer; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.Stories.recorder.DualCameraView; import org.telegram.ui.Stories.recorder.StoryRecorder; import org.telegram.ui.bots.BotBiometry; @@ -266,13 +272,10 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.time.DayOfWeek; import java.time.LocalDate; import java.time.Period; -import java.time.format.TextStyle; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -380,6 +383,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private ActionBarMenuItem editItem; private ActionBarMenuItem otherItem; private ActionBarMenuItem searchItem; + private ActionBarMenuSubItem editColorItem; + private ActionBarMenuSubItem linkItem; + private ActionBarMenuSubItem setUsernameItem; private ImageView ttlIconView; private ActionBarMenuItem qrItem; private ActionBarMenuSubItem autoDeleteItem; @@ -401,6 +407,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private boolean hasVoiceChatItem; private boolean isTopic; private boolean openSimilar; + private boolean myProfile; private boolean scrolling; @@ -506,6 +513,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private final static int gift_premium = 38; private final static int channel_stories = 39; private final static int edit_color = 40; + private final static int edit_profile = 41; + private final static int copy_link_profile = 42; + private final static int set_username = 43; private Rect rect = new Rect(); @@ -523,6 +533,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private int setUsernameRow; private int bioRow; private int phoneSuggestionSectionRow; + private int graceSuggestionRow; + private int graceSuggestionSectionRow; private int phoneSuggestionRow; private int passwordSuggestionSectionRow; private int passwordSuggestionRow; @@ -707,6 +719,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private ImageReceiver fallbackImage; private boolean loadingBoostsStats; private boolean waitCanSendStoryRequest; + private FrameLayout bottomButtonsContainer; + private FrameLayout[] bottomButtonContainer; + private SpannableStringBuilder bottomButtonPostText; + private ButtonWithCounterView[] bottomButton; + private Runnable applyBulletin; public static ProfileActivity of(long dialogId) { Bundle bundle = new Bundle(); @@ -1453,7 +1470,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (t > 0) { consumed[1] -= dy; } - if (consumed[1] > 0) { + if (innerListView != null && consumed[1] > 0) { innerListView.scrollBy(0, consumed[1]); } } @@ -1745,6 +1762,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. vcardFirstName = arguments.getString("vcard_first_name"); vcardLastName = arguments.getString("vcard_last_name"); reportSpam = arguments.getBoolean("reportSpam", false); + myProfile = arguments.getBoolean("my_profile", false); if (!expandPhoto) { expandPhoto = arguments.getBoolean("expandPhoto", false); if (expandPhoto) { @@ -1857,6 +1875,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().addObserver(this, NotificationCenter.storiesReadUpdated); getNotificationCenter().addObserver(this, NotificationCenter.userIsPremiumBlockedUpadted); + getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); updateRowsIds(); if (listAdapter != null) { @@ -1879,6 +1898,28 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); } } + + Bulletin.addDelegate(this, new Bulletin.Delegate() { + @Override + public int getTopOffset(int tag) { + return AndroidUtilities.statusBarHeight; + } + + @Override + public int getBottomOffset(int tag) { + if (bottomButtonsContainer == null) { + return 0; + } + final float stories = Math.min(1f, 1f - Math.abs(sharedMediaLayout.getTabProgress() - SharedMediaLayout.TAB_STORIES)); + final float archivedStories = Math.min(1f, 1f - Math.abs(sharedMediaLayout.getTabProgress() - SharedMediaLayout.TAB_ARCHIVED_STORIES)); + return (int) (dp(72) - bottomButtonsContainer.getTranslationY() - archivedStories * bottomButtonContainer[1].getTranslationY() - stories * bottomButtonContainer[0].getTranslationY()); + } + + @Override + public boolean bottomOffsetAnimated() { + return bottomButtonsContainer == null; + } + }); return true; } @@ -1929,6 +1970,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.storiesReadUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.userIsPremiumBlockedUpadted); + getNotificationCenter().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); if (avatarsViewPager != null) { avatarsViewPager.onDestroy(); @@ -1965,6 +2007,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. birthdayFetcher.detach(true); birthdayFetcher = null; } + + if (applyBulletin != null) { + Runnable runnable = applyBulletin; + applyBulletin = null; + AndroidUtilities.runOnUIThread(runnable); + } } @Override @@ -2223,6 +2271,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } presentFragment(fragment); } + } else if (id == edit_profile) { + presentFragment(new UserInfoActivity()); } else if (id == invite_to_group) { final TLRPC.User user = getMessagesController().getUser(userId); if (user == null) { @@ -2409,7 +2459,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (id == edit_info) { presentFragment(new UserInfoActivity()); } else if (id == edit_color) { + if (!getUserConfig().isPremium()) { + showDialog(new PremiumFeatureBottomSheet(ProfileActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_NAME_COLOR, true)); + return; + } presentFragment(new PeerColorActivity(0).startOnProfile().setOnApplied(ProfileActivity.this)); + } else if (id == copy_link_profile) { + TLRPC.User user = getMessagesController().getUser(userId); + AndroidUtilities.addToClipboard(getMessagesController().linkPrefix + "/" + UserObject.getPublicUsername(user)); + } else if (id == set_username) { + presentFragment(new ChangeUsernameActivity()); } else if (id == logout) { presentFragment(new LogoutActivity()); } else if (id == set_as_main) { @@ -2543,7 +2602,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getMessagesController().deleteUserPhoto(inputPhoto); getMessagesStorage().clearUserPhoto(userId, photo.id); } - if (avatarsViewPager.removePhotoAtIndex(position)) { + if (avatarsViewPager.removePhotoAtIndex(position) || avatarsViewPager.getRealCount() <= 0) { avatarsViewPager.setVisibility(View.GONE); avatarImage.setForegroundAlpha(1f); avatarContainer.setVisibility(View.VISIBLE); @@ -3044,6 +3103,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. protected boolean includeSavedDialogs() { return dialogId == getUserConfig().getClientUserId() && !saved; } + @Override + protected boolean isSelf() { + return myProfile; + } + + @Override + protected boolean isStoriesView() { + return myProfile; + } @Override protected void onSearchStateChanged(boolean expanded) { @@ -3085,11 +3153,79 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. protected int getInitialTab() { return TAB_STORIES; } + + @Override + protected void showActionMode(boolean show) { + super.showActionMode(show); + if (myProfile) { + disableScroll(show); + + int a = getSelectedTab() - SharedMediaLayout.TAB_STORIES; + if (a < 0 || a > 1) return; + bottomButtonContainer[a] + .animate() + .translationY(show || a == 0 && MessagesController.getInstance(currentAccount).storiesEnabled() ? 0 : dp(72)) + .setDuration(320) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .setUpdateListener(anm -> updateBottomButtonY()) + .start(); + } + } + @Override + protected void onTabProgress(float progress) { + super.onTabProgress(progress); + if (myProfile) { + bottomButtonContainer[0].setTranslationX((SharedMediaLayout.TAB_STORIES - progress) * sharedMediaLayout.getMeasuredWidth()); + bottomButtonContainer[1].setTranslationX((SharedMediaLayout.TAB_ARCHIVED_STORIES - progress) * sharedMediaLayout.getMeasuredWidth()); + updateBottomButtonY(); + } + } + + @Override + protected void onActionModeSelectedUpdate(SparseArray messageObjects) { + super.onActionModeSelectedUpdate(messageObjects); + if (myProfile) { + final int count = messageObjects.size(); + int a = getSelectedTab() - SharedMediaLayout.TAB_STORIES; + if (a < 0 || a > 1) return; + if (a == 0) { + bottomButton[a].setText(count > 0 || !MessagesController.getInstance(currentAccount).storiesEnabled() ? formatPluralString("ArchiveStories", count) : bottomButtonPostText, true); + } + bottomButton[a].setCount(count, true); + } + } + + @Override + public void openStoryRecorder() { + StoryRecorder.getInstance(getParentActivity(), currentAccount) + .selectedPeerId(getDialogId()) + .canChangePeer(false) + .closeToWhenSent(new StoryRecorder.ClosingViewProvider() { + @Override + public void preLayout(long dialogId, Runnable runnable) { + avatarImage.setHasStories(needInsetForStories()); + if (dialogId == getDialogId()) { + collapseAvatarInstant(); + } + AndroidUtilities.runOnUIThread(runnable, 30); + } + + @Override + public StoryRecorder.SourceView getView(long dialogId) { + if (dialogId != getDialogId()) { + return null; + } + updateAvatarRoundRadius(); + return StoryRecorder.SourceView.fromAvatarImage(avatarImage, ChatObject.isForum(currentChat)); + } + }) + .open(StoryRecorder.SourceView.fromFloatingButton(floatingButtonContainer), true); + } }; sharedMediaLayout.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT)); ActionBarMenu menu = actionBar.createMenu(); - if (userId == getUserConfig().clientUserId) { + if (userId == getUserConfig().clientUserId && !myProfile) { qrItem = menu.addItem(qr_button, R.drawable.msg_qr_mini, getResourceProvider()); qrItem.setContentDescription(LocaleController.getString("GetQRCode", R.string.GetQRCode)); updateQrItemVisibility(false); @@ -3097,7 +3233,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ContactsController.getInstance(currentAccount).loadPrivacySettings(); } } - if (imageUpdater != null) { + if (imageUpdater != null && !myProfile) { searchItem = menu.addItem(search_button, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override @@ -3141,8 +3277,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. callItem = menu.addItem(call_item, R.drawable.ic_call); callItem.setContentDescription(LocaleController.getString("Call", R.string.Call)); } - editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); - editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + if (myProfile) { + editItem = menu.addItem(edit_profile, R.drawable.group_edit_profile); + editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + } else { + editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); + editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + } otherItem = menu.addItem(10, R.drawable.ic_ab_other, resourcesProvider); ttlIconView = new ImageView(context); ttlIconView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); @@ -3211,6 +3352,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (sharedMediaLayout.canEditStories() && sharedMediaLayout != null && sharedMediaLayout.isActionModeShown() && sharedMediaLayout.getClosestTab() == SharedMediaLayout.TAB_STORIES) { + return false; + } + return super.onInterceptTouchEvent(e); + } + @Override public boolean onTouchEvent(MotionEvent e) { final int action = e.getAction(); @@ -3272,6 +3421,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } super.dispatchDraw(canvas); } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + updateBottomButtonY(); + } }; listView.setVerticalScrollBarEnabled(false); DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator() { @@ -3306,6 +3461,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. protected long getAddAnimationDelay(long removeDuration, long moveDuration, long changeDuration) { return 0; } + + @Override + protected void onMoveAnimationUpdate(RecyclerView.ViewHolder holder) { + super.onMoveAnimationUpdate(holder); + updateBottomButtonY(); + } }; listView.setItemAnimator(defaultItemAnimator); defaultItemAnimator.setMoveDelay(0); @@ -3430,7 +3591,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (button != null) { button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); } - } if (position == settingsKeyRow) { + } else if (position == settingsKeyRow) { Bundle args = new Bundle(); args.putInt("chat_id", DialogObject.getEncryptedChatId(dialogId)); presentFragment(new IdenticonActivity(args)); @@ -3441,7 +3602,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. NotificationsCheckCell checkCell = (NotificationsCheckCell) view; boolean checked = !checkCell.isChecked(); - boolean defaultEnabled = getNotificationsController().isGlobalNotificationsEnabled(did); + boolean defaultEnabled = getNotificationsController().isGlobalNotificationsEnabled(did, false, false); String key = NotificationsController.getSharedPrefKey(did, topicId); if (checked) { @@ -3715,48 +3876,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. layoutManager.scrollToPositionWithOffset(savedScrollPosition, savedScrollOffset - listView.getPaddingTop()); } } else if (position == bizLocationRow) { - if (userInfo == null || userInfo.business_location == null) return; - if (userInfo.business_location.geo_point != null) { - LocationActivity fragment = new LocationActivity(3) { - @Override - protected boolean disablePermissionCheck() { - return true; - } - }; - fragment.setResourceProvider(resourcesProvider); - TLRPC.TL_message message = new TLRPC.TL_message(); - message.local_id = -1; - message.peer_id = getMessagesController().getPeer(dialogId); - TLRPC.TL_messageMediaGeo media = new TLRPC.TL_messageMediaGeo(); - media.geo = userInfo.business_location.geo_point; - media.address = userInfo.business_location.address; - message.media = media; - fragment.setSharingAllowed(false); - fragment.setMessageObject(new MessageObject(UserConfig.selectedAccount, message, false, false)); - presentFragment(fragment); - } else { - String domain; - if (BuildVars.isHuaweiStoreApp()) { - domain = "mapapp://navigation"; - } else { - domain = "http://maps.google.com/maps"; - } -// if (myLocation != null) { -// try { -// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?saddr=%f,%f&daddr=%f,%f", myLocation.getLatitude(), myLocation.getLongitude(), daddrLat, daddrLong))); -// getParentActivity().startActivity(intent); -// } catch (Exception e) { -// FileLog.e(e); -// } -// } else { - try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?q=" + userInfo.business_location.address ))); - getParentActivity().startActivity(intent); - } catch (Exception e) { - FileLog.e(e); - } -// } - } + openLocation(false); } else if (position == channelRow) { if (userInfo == null) return; Bundle args = new Bundle(); @@ -3766,6 +3886,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (birthdayEffect != null && birthdayEffect.start()) { return; } + if (editRow(view, position)) { + return; + } TextDetailCell cell = (TextDetailCell) view; if (cell.hasImage()) { onTextDetailCellImageClicked(cell.getImageView()); @@ -3815,8 +3938,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.photoViewerBlur ? "do not blur in photoviewer" : "blur in photoviewer") : null, !SharedConfig.payByInvoice ? "Enable Invoice Payment" : "Disable Invoice Payment", BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null, - Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? (!SharedConfig.useCamera2 ? "Use Camera 2 API" : "Use old Camera 1 API") : null, - BuildVars.DEBUG_VERSION ? "Clear bot biometry data" : null + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? (!SharedConfig.isUsingCamera2(currentAccount) ? "Use Camera 2 API" : "Use old Camera 1 API") : null, + BuildVars.DEBUG_VERSION ? "Clear bot biometry data" : null, + BuildVars.DEBUG_PRIVATE_VERSION ? "Clear all login tokens" : null }; builder.setItems(items, (dialog, which) -> { @@ -4070,9 +4194,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (which == 26) { getMediaDataController().loadAttachMenuBots(false, true); } else if (which == 27) { - SharedConfig.toggleUseCamera2(); + SharedConfig.toggleUseCamera2(currentAccount); } else if (which == 28) { BotBiometry.clear(); + } else if (which == 29) { + AuthTokensHelper.clearLogInTokens(); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -4094,6 +4220,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } return onMemberClick(participant, true, view); } else if (position == birthdayRow) { + if (editRow(view, position)) return true; if (userInfo == null) return false; try { AndroidUtilities.addToClipboard(UserInfoActivity.birthdayString(userInfo.birthday)); @@ -4103,6 +4230,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } return true; } else { + if (editRow(view, position)) return true; return processOnClickOrPress(position, view, view.getWidth() / 2f, (int) (view.getHeight() * .75f)); } } @@ -4233,8 +4361,19 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { removeSelfFromStack(); + TLRPC.User user = getMessagesController().getUser(userId); + if (user != null && chat != null && userId != 0 && fragment != null && fragment.banning && fragment.getParentLayout() != null) { + for (BaseFragment fragment : fragment.getParentLayout().getFragmentStack()) { + if (fragment instanceof ChannelAdminLogActivity) { + ((ChannelAdminLogActivity) fragment).reloadLastMessages(); + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.createRemoveFromChatBulletin(fragment, user, chat.title).show(); + }); + return; + } + } + } } - @Override public void didChangeOwner(TLRPC.User user) { undoView.showWithAction(-chatId, currentChat.megagroup ? UndoView.ACTION_OWNER_TRANSFERED_GROUP : UndoView.ACTION_OWNER_TRANSFERED_CHANNEL, user); @@ -4247,7 +4386,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. textView.setTextColor(getThemedColor(Theme.key_text_RedRegular)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setGravity(Gravity.CENTER); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); textView.setText(LocaleController.getString("BanFromTheGroup", R.string.BanFromTheGroup)); frameLayout1.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 1, 0, 0)); @@ -4708,7 +4847,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (participantsMap != null && !usersEndReached && layoutManager.findLastVisibleItemPosition() > membersEndRow - 8) { getChannelParticipants(false); } - sharedMediaLayout.setPinnedToTop(sharedMediaLayout.getY() == 0); + sharedMediaLayout.setPinnedToTop(sharedMediaLayout.getY() <= 0); + updateBottomButtonY(); } }); @@ -4844,9 +4984,143 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. createBirthdayEffect(); createFloatingActionButton(getContext()); + + if (myProfile) { + bottomButtonsContainer = new FrameLayout(context); + contentView.addView(bottomButtonsContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 72 + (1 / AndroidUtilities.density), Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + + bottomButtonContainer = new FrameLayout[2]; + bottomButton = new ButtonWithCounterView[2]; + for (int a = 0; a < 2; ++a) { + bottomButtonContainer[a] = new FrameLayout(context); + bottomButtonContainer[a].setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + + View shadow = new View(context); + shadow.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundGray)); + bottomButtonContainer[a].addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1 / AndroidUtilities.density, Gravity.TOP | Gravity.FILL_HORIZONTAL)); + + bottomButton[a] = new ButtonWithCounterView(context, resourcesProvider); + if (a == 0) { + bottomButtonPostText = new SpannableStringBuilder("c"); + bottomButtonPostText.setSpan(new ColoredImageSpan(R.drawable.filled_premium_camera), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + bottomButtonPostText.append(" ").append(getString(R.string.StoriesAddPost)); + bottomButton[a].setText(bottomButtonPostText, false); + } else { + bottomButton[a].setText(getString(R.string.StorySave), false); + } + final int finalA = a; + bottomButton[a].setOnClickListener(v -> { + if (finalA == 0 && !sharedMediaLayout.isActionModeShown()) { + if (!getMessagesController().storiesEnabled()) { + showDialog(new PremiumFeatureBottomSheet(this, PremiumPreviewFragment.PREMIUM_FEATURE_STORIES, true)); + return; + } + getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); + StoryRecorder.getInstance(getParentActivity(), getCurrentAccount()) + .closeToWhenSent(new StoryRecorder.ClosingViewProvider() { + @Override + public void preLayout(long dialogId, Runnable runnable) { + avatarImage.setHasStories(needInsetForStories()); + if (dialogId == getDialogId()) { + collapseAvatarInstant(); + } + AndroidUtilities.runOnUIThread(runnable, 30); + } + + @Override + public StoryRecorder.SourceView getView(long dialogId) { + if (dialogId != getDialogId()) { + return null; + } + updateAvatarRoundRadius(); + return StoryRecorder.SourceView.fromAvatarImage(avatarImage, ChatObject.isForum(currentChat)); + } + }) + .open(null); + } else { + final long dialogId = getUserConfig().getClientUserId(); + if (applyBulletin != null) { + applyBulletin.run(); + applyBulletin = null; + } + Bulletin.hideVisible(); + boolean pin = sharedMediaLayout.getClosestTab() == SharedMediaLayout.TAB_ARCHIVED_STORIES; + int count = 0; + ArrayList storyItems = new ArrayList<>(); + SparseArray actionModeMessageObjects = sharedMediaLayout.getActionModeSelected(); + if (actionModeMessageObjects != null) { + for (int i = 0; i < actionModeMessageObjects.size(); ++i) { + MessageObject messageObject = actionModeMessageObjects.valueAt(i); + if (messageObject.storyItem != null) { + storyItems.add(messageObject.storyItem); + count++; + } + } + } + sharedMediaLayout.closeActionMode(false); + if (pin) { + sharedMediaLayout.scrollToPage(SharedMediaLayout.TAB_STORIES); + } + if (storyItems.isEmpty()) { + return; + } + boolean[] pastValues = new boolean[storyItems.size()]; + for (int i = 0; i < storyItems.size(); ++i) { + TL_stories.StoryItem storyItem = storyItems.get(i); + pastValues[i] = storyItem.pinned; + storyItem.pinned = pin; + } + getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); + final boolean[] undone = new boolean[] { false }; + applyBulletin = () -> { + getMessagesController().getStoriesController().updateStoriesPinned(dialogId, storyItems, pin, null); + }; + final Runnable undo = () -> { + undone[0] = true; + AndroidUtilities.cancelRunOnUIThread(applyBulletin); + for (int i = 0; i < storyItems.size(); ++i) { + TL_stories.StoryItem storyItem = storyItems.get(i); + storyItem.pinned = pastValues[i]; + } + getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); + }; + Bulletin bulletin; + if (pin) { + bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.contact_check, LocaleController.formatPluralString("StorySavedTitle", count), LocaleController.getString(R.string.StorySavedSubtitle), LocaleController.getString(R.string.Undo), undo).show(); + } else { + bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.chats_archived, LocaleController.formatPluralString("StoryArchived", count), LocaleController.getString(R.string.Undo), Bulletin.DURATION_PROLONG, undo).show(); + } + bulletin.setOnHideListener(() -> { + if (!undone[0] && applyBulletin != null) { + applyBulletin.run(); + } + applyBulletin = null; + }); + } + }); + bottomButtonContainer[a].addView(bottomButton[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 12, 12, 12, 12)); + + bottomButtonsContainer.addView(bottomButtonContainer[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + if (a == 1 || !getMessagesController().storiesEnabled()) { + bottomButtonContainer[a].setTranslationY(dp(72)); + } + } + } + return fragmentView; } + private void updateBottomButtonY() { + if (bottomButtonsContainer == null) { + return; + } + bottomButtonsContainer.setTranslationY(sharedMediaLayout.isAttachedToWindow() ? Math.max(0, dp(72 + 64 + 48) - (listView.getMeasuredHeight() - sharedMediaLayout.getY())) : dp(72)); + Bulletin bulletin = Bulletin.getVisibleBulletin(); + if (bulletin != null) { + bulletin.updatePosition(); + } + } + FrameLayout floatingButtonContainer; RLottieImageView floatingButton; boolean floatingHidden; @@ -5726,6 +6000,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getConnectionsManager().bindRequestToGuid(reqId, getClassGuid()); } } else { + if (editRow(view, position)) return true; + if (usernameObj != null && !usernameObj.editable) { TL_fragment.TL_getCollectibleInfo req = new TL_fragment.TL_getCollectibleInfo(); TL_fragment.TL_inputCollectibleUsername input = new TL_fragment.TL_inputCollectibleUsername(); @@ -5760,6 +6036,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } return true; } else if (position == phoneRow || position == numberRow) { + if (editRow(view, position)) return true; + final TLRPC.User user = getMessagesController().getUser(userId); if (user == null || user.phone == null || user.phone.length() == 0 || getParentActivity() == null) { return false; @@ -5927,6 +6205,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (position == bioRow && (userInfo == null || TextUtils.isEmpty(userInfo.about))) { return false; } + if (editRow(view, position)) return true; if (view instanceof AboutLinkCell && ((AboutLinkCell) view).onClick()) { return false; } @@ -6054,41 +6333,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. final String finalText; if (position == bizHoursRow) { if (userInfo.business_work_hours == null) return false; - ArrayList[] days = OpeningHoursActivity.getDaysHours(userInfo.business_work_hours.weekly_open); - StringBuilder sb = new StringBuilder(); - if (userInfo.user != null) { - sb.append(formatString(R.string.BusinessHoursCopyHeader, UserObject.getUserName(userInfo.user))).append("\n"); - } - for (int i = 0; i < days.length; ++i) { - ArrayList periods = days[i]; - String day = DayOfWeek.values()[i].getDisplayName(TextStyle.FULL, LocaleController.getInstance().getCurrentLocale()); - day = day.substring(0, 1).toUpperCase() + day.substring(1); - sb.append(day).append(": "); - if (OpeningHoursActivity.isFull(periods)) { - sb.append(LocaleController.getString(R.string.BusinessHoursProfileOpen)); - } else if (periods.isEmpty()) { - sb.append(LocaleController.getString(R.string.BusinessHoursProfileClose)); - } else { - for (int j = 0; j < periods.size(); ++j) { - if (j > 0) sb.append(", "); - OpeningHoursActivity.Period p = periods.get(j); - sb.append(OpeningHoursActivity.Period.timeToString(p.start)); - sb.append(" - "); - sb.append(OpeningHoursActivity.Period.timeToString(p.end)); - } - } - sb.append("\n"); - } - TLRPC.TL_timezone timezone = TimezonesController.getInstance(currentAccount).findTimezone(userInfo.business_work_hours.timezone_id); - Calendar calendar = Calendar.getInstance(); - int currentUtcOffset = calendar.getTimeZone().getRawOffset() / 1000; - int valueUtcOffset = timezone == null ? 0 : timezone.utc_offset; - int utcOffset = (currentUtcOffset - valueUtcOffset) / 60; - if (utcOffset != 0 && timezone != null) { - sb.append(formatString(R.string.BusinessHoursCopyFooter, TimezonesController.getInstance(currentAccount).getTimezoneName(timezone, true))); - } - finalText = sb.toString(); + finalText = OpeningHoursActivity.toString(currentAccount, userInfo.user, userInfo.business_work_hours); } else if (position == bizLocationRow) { + if (editRow(view, position)) return true; if (userInfo.business_location == null) return false; finalText = userInfo.business_location.address; } else return true; @@ -6596,6 +6843,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. mediaCounterTextView.setText(onlineTextView[1].getText()); } else if (id == SharedMediaLayout.TAB_STORIES) { mediaCounterTextView.setText(LocaleController.formatPluralString("ProfileStoriesCount", sharedMediaLayout.getStoriesCount(id))); + } else if (id == SharedMediaLayout.TAB_ARCHIVED_STORIES) { + mediaCounterTextView.setText(LocaleController.formatPluralString("ProfileStoriesArchiveCount", sharedMediaLayout.getStoriesCount(id))); } else if (id == SharedMediaLayout.TAB_RECOMMENDED_CHANNELS) { MessagesController.ChannelRecommendations rec = MessagesController.getInstance(currentAccount).getChannelRecommendations(chatId); mediaCounterTextView.setText(LocaleController.formatPluralString("Channels", rec == null ? 0 : rec.chats.size() + rec.more)); @@ -7398,10 +7647,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. avatarImage.setHasStories(needInsetForStories()); updateAvatarRoundRadius(); } + if (userInfo != null) { + storyView.setStories(userInfo.stories); + } else if (chatInfo != null) { + storyView.setStories(chatInfo.stories); + } } else if (id == NotificationCenter.userIsPremiumBlockedUpadted) { if (otherItem != null) { otherItem.setSubItemShown(start_secret_chat, !getMessagesController().isUserPremiumBlocked(userId)); } + updateEditColorIcon(); + } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { + updateEditColorIcon(); } } @@ -7515,6 +7772,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (flagSecure != null) { flagSecure.attach(); } + updateItemsUsername(); } @Override @@ -7575,7 +7833,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } public boolean isSettings() { - return imageUpdater != null; + return imageUpdater != null && !myProfile; } @Override @@ -8182,6 +8440,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. phoneSuggestionSectionRow = -1; phoneSuggestionRow = -1; passwordSuggestionSectionRow = -1; + graceSuggestionRow = -1; + graceSuggestionSectionRow = -1; passwordSuggestionRow = -1; settingsSectionRow = -1; settingsSectionRow2 = -1; @@ -8276,7 +8536,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. hasMedia = chatInfo.stories_pinned_available; } if (!hasMedia) { - if (MessagesController.ChannelRecommendations.hasRecommendations(currentAccount, chatId)) { + if (chatId != 0 && MessagesController.ChannelRecommendations.hasRecommendations(currentAccount, chatId)) { hasMedia = true; } } @@ -8287,7 +8547,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } TLRPC.User user = getMessagesController().getUser(userId); - if (UserObject.isUserSelf(user)) { + if (UserObject.isUserSelf(user) && !myProfile) { if (avatarBig == null && (user.photo == null || !(user.photo.photo_big instanceof TLRPC.TL_fileLocation_layer97) && !(user.photo.photo_big instanceof TLRPC.TL_fileLocationToBeDeprecated)) && (avatarsViewPager == null || avatarsViewPager.getRealCount() == 0)) { setAvatarRow = rowCount++; setAvatarSectionRow = rowCount++; @@ -8300,11 +8560,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. settingsSectionRow = rowCount++; Set suggestions = getMessagesController().pendingSuggestions; - if (suggestions.contains("VALIDATE_PHONE_NUMBER")) { + if (suggestions.contains("PREMIUM_GRACE")) { + graceSuggestionRow = rowCount++; + graceSuggestionSectionRow = rowCount++; + } else if (suggestions.contains("VALIDATE_PHONE_NUMBER")) { phoneSuggestionRow = rowCount++; phoneSuggestionSectionRow = rowCount++; - } - if (suggestions.contains("VALIDATE_PASSWORD")) { + } else if (suggestions.contains("VALIDATE_PASSWORD")) { passwordSuggestionRow = rowCount++; passwordSuggestionSectionRow = rowCount++; } @@ -8316,7 +8578,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. dataRow = rowCount++; liteModeRow = rowCount++; // stickersRow = rowCount++; - if (getMessagesController().filtersEnabled || !getMessagesController().dialogFilters.isEmpty() || true) { + if (getMessagesController().filtersEnabled || !getMessagesController().dialogFilters.isEmpty()) { filtersRow = rowCount++; } devicesRow = rowCount++; @@ -8411,11 +8673,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } boolean divider = false; - if (showAddToContacts && user != null && !user.contact && !user.bot && !UserObject.isService(user.id)) { + if (!myProfile && showAddToContacts && user != null && !user.contact && !user.bot && !UserObject.isService(user.id)) { addToContactsRow = rowCount++; divider = true; } - if (reportReactionMessageId != 0 && !ContactsController.getInstance(currentAccount).isContact(userId)) { + if (!myProfile && reportReactionMessageId != 0 && !ContactsController.getInstance(currentAccount).isContact(userId)) { reportReactionRow = rowCount++; divider = true; } @@ -8423,7 +8685,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. reportDividerRow = rowCount++; } - if (hasMedia || userInfo != null && userInfo.common_chats_count != 0) { + if (hasMedia || userInfo != null && userInfo.common_chats_count != 0 || myProfile) { sharedMediaRow = rowCount++; } else if (lastSectionRow == -1 && needSendMessage) { sendMessageRow = rowCount++; @@ -8605,7 +8867,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. verifiedDrawable[a] = Theme.profile_verifiedDrawable.getConstantState().newDrawable().mutate(); verifiedCheckDrawable[a] = Theme.profile_verifiedCheckDrawable.getConstantState().newDrawable().mutate(); if (a == 1 && peerColor != null) { - int color = Theme.adaptHSV(ColorUtils.blendARGB(peerColor.getColor2(), peerColor.hasColor6(Theme.isCurrentThemeDark()) ? peerColor.getColor5() : peerColor.getColor3(), .4f), +.1f, Theme.isCurrentThemeDark() ? -.1f : -.08f); + int color = Theme.adaptHSV(peerColor.hasColor6(Theme.isCurrentThemeDark()) ? peerColor.getColor5() : peerColor.getColor3(), +.1f, Theme.isCurrentThemeDark() ? -.1f : -.08f); verifiedDrawable[1].setColorFilter(AndroidUtilities.getOffsetColor(color, getThemedColor(Theme.key_player_actionBarTitle), mediaHeaderAnimationProgress, 1.0f), PorterDuff.Mode.MULTIPLY); color = Color.WHITE; verifiedCheckDrawable[1].setColorFilter(AndroidUtilities.getOffsetColor(color, getThemedColor(Theme.key_windowBackgroundWhite), mediaHeaderAnimationProgress, 1.0f), PorterDuff.Mode.MULTIPLY); @@ -9353,14 +9615,25 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. videoCallItemVisible = false; canSearchMembers = false; boolean selfUser = false; + if (userId != 0) { TLRPC.User user = getMessagesController().getUser(userId); if (user == null) { return; } if (UserObject.isUserSelf(user)) { + editItemVisible = myProfile; otherItem.addSubItem(edit_info, R.drawable.msg_edit, LocaleController.getString(R.string.EditInfo)); - otherItem.addSubItem(edit_color, R.drawable.msg_colors, LocaleController.getString(R.string.EditProfileColor)); + if (imageUpdater != null) { + otherItem.addSubItem(add_photo, R.drawable.msg_addphoto, LocaleController.getString("AddPhoto", R.string.AddPhoto)); + } + editColorItem = otherItem.addSubItem(edit_color, R.drawable.menu_profile_colors, LocaleController.getString(R.string.ProfileColorEdit)); + updateEditColorIcon(); + if (myProfile) { + setUsernameItem = otherItem.addSubItem(set_username, R.drawable.menu_username_change, getString(R.string.ProfileUsernameEdit)); + linkItem = otherItem.addSubItem(copy_link_profile, R.drawable.msg_link2, getString(R.string.ProfileCopyLink)); + updateItemsUsername(); + } selfUser = true; } else { if (user.bot && user.bot_can_edit) { @@ -9502,7 +9775,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (imageUpdater != null) { - otherItem.addSubItem(add_photo, R.drawable.msg_addphoto, LocaleController.getString("AddPhoto", R.string.AddPhoto)); otherItem.addSubItem(set_as_main, R.drawable.msg_openprofile, LocaleController.getString("SetAsMain", R.string.SetAsMain)); otherItem.addSubItem(gallery_menu_save, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); //otherItem.addSubItem(edit_avatar, R.drawable.photo_paint, LocaleController.getString("EditPhoto", R.string.EditPhoto)); @@ -9514,7 +9786,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.hideSubItem(gallery_menu_save); } - if (selfUser) { + if (selfUser && !myProfile) { otherItem.addSubItem(logout, R.drawable.msg_leave, LocaleController.getString("LogOut", R.string.LogOut)); } if (!isPulledDown) { @@ -10453,10 +10725,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override protected void onYesClick(int type) { getNotificationCenter().removeObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); - getMessagesController().removeSuggestion(0, type == SettingsSuggestionCell.TYPE_PHONE ? "VALIDATE_PHONE_NUMBER" : "VALIDATE_PASSWORD"); + if (type == SettingsSuggestionCell.TYPE_GRACE) { + Browser.openUrl(getContext(), getMessagesController().premiumManageSubscriptionUrl); + getMessagesController().removeSuggestion(0, "PREMIUM_GRACE"); + updateListAnimated(false); + } else { + getMessagesController().removeSuggestion(0, type == SettingsSuggestionCell.TYPE_PHONE ? "VALIDATE_PHONE_NUMBER" : "VALIDATE_PASSWORD"); + updateListAnimated(false); + } getNotificationCenter().addObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); - int oldRow = type == SettingsSuggestionCell.TYPE_PHONE ? phoneSuggestionRow : passwordSuggestionRow; - updateListAnimated(false); } @Override @@ -10562,7 +10839,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. isTopic || bizHoursRow != -1 || bizLocationRow != -1 ); - containsGift = today && !getMessagesController().premiumPurchaseBlocked(); + containsGift = !myProfile && today && !getMessagesController().premiumPurchaseBlocked(); } } else if (position == phoneRow) { String text; @@ -10908,7 +11185,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (hasOverride) { enabled = true; } else { - enabled = getNotificationsController().isGlobalNotificationsEnabled(did); + enabled = getNotificationsController().isGlobalNotificationsEnabled(did, false, false); } } else if (value == 1) { enabled = true; @@ -10985,7 +11262,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. break; case VIEW_TYPE_SUGGESTION: SettingsSuggestionCell suggestionCell = (SettingsSuggestionCell) holder.itemView; - suggestionCell.setType(position == passwordSuggestionRow ? SettingsSuggestionCell.TYPE_PASSWORD : SettingsSuggestionCell.TYPE_PHONE); + if (position == passwordSuggestionRow) { + suggestionCell.setType(SettingsSuggestionCell.TYPE_PASSWORD); + } else if (position == phoneSuggestionRow) { + suggestionCell.setType(SettingsSuggestionCell.TYPE_PHONE); + } else if (position == graceSuggestionRow) { + suggestionCell.setType(SettingsSuggestionCell.TYPE_GRACE); + } break; case VIEW_TYPE_ADDTOGROUP_INFO: TextInfoPrivacyCell addToGroupInfo = (TextInfoPrivacyCell) holder.itemView; @@ -10997,7 +11280,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. textCheckCell.setTextAndCheck(LocaleController.getString("Notifications", R.string.Notifications), !getMessagesController().isDialogMuted(getDialogId(), topicId), false); break; case VIEW_TYPE_LOCATION: - ((ProfileLocationCell) holder.itemView).set(userInfo != null ? userInfo.business_location : null, notificationsDividerRow < 0); + ((ProfileLocationCell) holder.itemView).set(userInfo != null ? userInfo.business_location : null, notificationsDividerRow < 0 && !myProfile); break; case VIEW_TYPE_HOURS: ProfileHoursCell hoursCell = (ProfileHoursCell) holder.itemView; @@ -11013,7 +11296,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. layoutManager.scrollToPositionWithOffset(savedScrollPosition, savedScrollOffset - listView.getPaddingTop()); } }); - hoursCell.set(userInfo != null ? userInfo.business_work_hours : null, hoursExpanded, hoursShownMine, notificationsDividerRow < 0 || bizLocationRow >= 0); + hoursCell.set(userInfo != null ? userInfo.business_work_hours : null, hoursExpanded, hoursShownMine, notificationsDividerRow < 0 && !myProfile || bizLocationRow >= 0); break; case VIEW_TYPE_CHANNEL: ((ProfileChannelCell) holder.itemView).set( @@ -11088,6 +11371,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { obj = getMessagesController().getChat(chatId); } + if (getContext() == null) { + return; + } FragmentUsernameBottomSheet.open(getContext(), FragmentUsernameBottomSheet.TYPE_USERNAME, usernameObj.username, obj, (TL_fragment.TL_collectibleInfo) res, getResourceProvider()); } else { BulletinFactory.showError(err); @@ -11185,7 +11471,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (position == infoSectionRow || position == lastSectionRow || position == membersSectionRow || position == secretSettingsSectionRow || position == settingsSectionRow || position == devicesSectionRow || position == helpSectionCell || position == setAvatarSectionRow || position == passwordSuggestionSectionRow || - position == phoneSuggestionSectionRow || position == premiumSectionsRow || position == reportDividerRow || position == channelDividerRow) { + position == phoneSuggestionSectionRow || position == premiumSectionsRow || position == reportDividerRow || + position == channelDividerRow || position == graceSuggestionSectionRow + ) { return VIEW_TYPE_SHADOW; } else if (position >= membersStartRow && position < membersEndRow) { return VIEW_TYPE_USER; @@ -11197,7 +11485,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return VIEW_TYPE_SHARED_MEDIA; } else if (position == versionRow) { return VIEW_TYPE_VERSION; - } else if (position == passwordSuggestionRow || position == phoneSuggestionRow) { + } else if (position == passwordSuggestionRow || position == phoneSuggestionRow || position == graceSuggestionRow) { return VIEW_TYPE_SUGGESTION; } else if (position == addToGroupInfoRow) { return VIEW_TYPE_ADDTOGROUP_INFO; @@ -12271,7 +12559,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. args.putLong("user_id", userId); presentFragment(new QrActivity(args)); } else if (parent.getTag() != null && ((int) parent.getTag()) == birthdayRow) { - TLRPC.User user = getMessagesController().getUser(dialogId); + if (userId == getUserConfig().getClientUserId()) { + presentFragment(new PremiumPreviewFragment("my_profile_gift")); + return; + } + TLRPC.User user = getMessagesController().getUser(userId); if (user == null || userInfo == null) return; ArrayList options = new ArrayList<>(userInfo.premium_gifts); if (options.isEmpty()) { @@ -12438,6 +12730,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. put(++pointer, phoneSuggestionSectionRow, sparseIntArray); put(++pointer, passwordSuggestionRow, sparseIntArray); put(++pointer, passwordSuggestionSectionRow, sparseIntArray); + put(++pointer, graceSuggestionRow, sparseIntArray); + put(++pointer, graceSuggestionSectionRow, sparseIntArray); put(++pointer, settingsSectionRow, sparseIntArray); put(++pointer, settingsSectionRow2, sparseIntArray); put(++pointer, notificationRow, sparseIntArray); @@ -12741,10 +13035,25 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public static class ShowDrawable extends Drawable implements SimpleTextView.PressableDrawable { - private final Text text; + public final AnimatedTextView.AnimatedTextDrawable textDrawable; public final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); public ShowDrawable(String string) { - text = new Text(string, 11); + textDrawable = new AnimatedTextView.AnimatedTextDrawable(); + textDrawable.setCallback(new Callback() { + @Override + public void invalidateDrawable(@NonNull Drawable who) { + if (view != null) { + view.invalidate(); + } + } + @Override + public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {} + @Override + public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {} + }); + textDrawable.setText(string); + textDrawable.setTextSize(dp(11)); + textDrawable.setGravity(Gravity.CENTER); backgroundPaint.setColor(0x1f000000); } @@ -12773,7 +13082,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. backgroundPaint.setAlpha((int) (wasAlpha * alpha)); canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(20), dp(20), backgroundPaint); backgroundPaint.setAlpha(wasAlpha); - text.draw(canvas, AndroidUtilities.rectTmp.left + dp(5.5f), AndroidUtilities.rectTmp.centerY(), textColor, alpha); + textDrawable.setTextColor(textColor); + textDrawable.setAlpha((int) (0xFF * alpha)); + textDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); + textDrawable.draw(canvas); canvas.restore(); } @@ -12791,7 +13103,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public int getIntrinsicWidth() { - return (int) (text.getCurrentWidth() + dp(11)); + return (int) (textDrawable.getAnimateToWidth() + dp(11)); } @Override @@ -12822,6 +13134,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public boolean isPressed() { return pressed; } + + private View view; + public void setView(View view) { + this.view = view; + } } public void setLoadingSpan(CharacterStyle span) { @@ -12851,4 +13168,320 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ((FrameLayout) fragmentView).addView(birthdayEffect, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL_HORIZONTAL | Gravity.TOP)); } + private void openLocation(boolean inMapsApp) { + if (userInfo == null || userInfo.business_location == null) return; + if (userInfo.business_location.geo_point != null && !inMapsApp) { + LocationActivity fragment = new LocationActivity(3) { + @Override + protected boolean disablePermissionCheck() { + return true; + } + }; + fragment.setResourceProvider(resourcesProvider); + TLRPC.TL_message message = new TLRPC.TL_message(); + message.local_id = -1; + message.peer_id = getMessagesController().getPeer(dialogId); + TLRPC.TL_messageMediaGeo media = new TLRPC.TL_messageMediaGeo(); + media.geo = userInfo.business_location.geo_point; + media.address = userInfo.business_location.address; + message.media = media; + fragment.setSharingAllowed(false); + fragment.setMessageObject(new MessageObject(UserConfig.selectedAccount, message, false, false)); + presentFragment(fragment); + } else { + String domain; + if (BuildVars.isHuaweiStoreApp()) { + domain = "mapapp://navigation"; + } else { + domain = "http://maps.google.com/maps"; + } +// if (myLocation != null) { +// try { +// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?saddr=%f,%f&daddr=%f,%f", myLocation.getLatitude(), myLocation.getLongitude(), daddrLat, daddrLong))); +// getParentActivity().startActivity(intent); +// } catch (Exception e) { +// FileLog.e(e); +// } +// } else { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?q=" + userInfo.business_location.address ))); + getParentActivity().startActivity(intent); + } catch (Exception e) { + FileLog.e(e); + } +// } + } + + } + + private boolean editRow(View view, int position) { + if (!myProfile) return false; + + if (view instanceof ProfileChannelCell) { + view = ((ProfileChannelCell) view).dialogCell; + } + + TLRPC.User user = getUserConfig().getCurrentUser(); + if (user == null) return false; + TLRPC.UserFull userFull = userInfo == null ? getMessagesController().getUserFull(user.id) : userInfo; + if (userFull == null) return false; + + String copyButton = getString(R.string.Copy); + String textToCopy = null; + if (position == channelInfoRow || position == userInfoRow || position == bioRow) { + textToCopy = userFull.about; + } else if (position == bizHoursRow) { + textToCopy = OpeningHoursActivity.toString(currentAccount, user, userFull.business_work_hours); + copyButton = getString(R.string.ProfileHoursCopy); + } else if (position == bizLocationRow) { + textToCopy = userFull.business_location.address; + copyButton = getString(R.string.ProfileLocationCopy); + } else if (position == usernameRow) { + textToCopy = UserObject.getPublicUsername(user); + if (textToCopy != null) textToCopy = "@" + textToCopy; + copyButton = getString(R.string.ProfileCopyUsername); + } else if (position == phoneRow) { + textToCopy = user.phone; + } else if (position == birthdayRow) { + textToCopy = UserInfoActivity.birthdayString(userInfo.birthday); + } + + ItemOptions itemOptions = ItemOptions.makeOptions(contentView, resourcesProvider, view); + itemOptions.setGravity(Gravity.LEFT); + + if (position == bizLocationRow && userFull.business_location != null) { + if (userFull.business_location.geo_point != null) { + itemOptions.add(R.drawable.msg_view_file, getString(R.string.ProfileLocationView), () -> { + openLocation(false); + }); + } + itemOptions.add(R.drawable.msg_map, getString(R.string.ProfileLocationMaps), () -> { + openLocation(true); + }); + } + + if (textToCopy != null) { + final String text = textToCopy; + itemOptions.add(R.drawable.msg_copy, copyButton, () -> { + AndroidUtilities.addToClipboard(text); + }); + } + + if (position == bizHoursRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileHoursEdit), () -> { + presentFragment(new OpeningHoursActivity()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.ProfileHoursRemove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.BusinessHoursClearTitle)); + builder.setMessage(LocaleController.getString(R.string.BusinessHoursClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updateBusinessWorkHours req = new TLRPC.TL_account_updateBusinessWorkHours(); + if (userFull != null) { + userFull.business_work_hours = null; + userFull.flags2 &=~ 1; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } else if (position == bizLocationRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileLocationEdit), () -> { + presentFragment(new org.telegram.ui.Business.LocationActivity()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.ProfileLocationRemove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.BusinessLocationClearTitle)); + builder.setMessage(LocaleController.getString(R.string.BusinessLocationClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updateBusinessLocation req = new TLRPC.TL_account_updateBusinessLocation(); + if (userFull != null) { + userFull.business_location = null; + userFull.flags2 &=~ 2; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } else if (position == usernameRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileUsernameEdit), () -> { + presentFragment(new ChangeUsernameActivity()); + }); + } else if (position == channelInfoRow || position == userInfoRow || position == bioRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileEditBio), () -> { + presentFragment(new UserInfoActivity()); + }); + } else if (position == phoneRow) { + itemOptions.add(R.drawable.menu_storage_path, getString(R.string.ProfilePhoneEdit), () -> { + presentFragment(new ActionIntroActivity(ActionIntroActivity.ACTION_TYPE_CHANGE_PHONE_NUMBER)); + }); + } else if (position == birthdayRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileBirthdayChange), () -> { + showDialog(AlertsCreator.createBirthdayPickerDialog(getContext(), getString(R.string.EditProfileBirthdayTitle), getString(R.string.EditProfileBirthdayButton), userFull.birthday, birthday -> { + TLRPC.TL_account_updateBirthday req = new TLRPC.TL_account_updateBirthday(); + req.flags |= 1; + req.birthday = birthday; + TLRPC.TL_birthday oldBirthday = userFull != null ? userFull.birthday : null; + if (userFull != null) { + userFull.flags2 |= 32; + userFull.birthday = birthday; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TLRPC.TL_boolTrue) { + BulletinFactory.of(ProfileActivity.this) + .createSimpleBulletin(R.raw.contact_check, LocaleController.getString(R.string.PrivacyBirthdaySetDone)) + .setDuration(Bulletin.DURATION_PROLONG).show(); + } else { + if (userFull != null) { + if (oldBirthday == null) { + userFull.flags2 &=~ 32; + } else { + userFull.flags2 |= 32; + } + userFull.birthday = oldBirthday; + getMessagesStorage().updateUserInfo(userFull, false); + } + if (err != null && err.text != null && err.text.startsWith("FLOOD_WAIT_")) { + if (getContext() != null) { + showDialog( + new AlertDialog.Builder(getContext(), resourceProvider) + .setTitle(getString(R.string.PrivacyBirthdayTooOftenTitle)) + .setMessage(getString(R.string.PrivacyBirthdayTooOftenMessage)) + .setPositiveButton(getString(R.string.OK), null) + .create() + ); + } + } else { + BulletinFactory.of(ProfileActivity.this) + .createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.UnknownError)) + .show(); + } + } + }), ConnectionsManager.RequestFlagDoNotWaitFloodWait); + }, () -> { + BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams(); + params.transitionFromLeft = true; + params.allowNestedScroll = false; + showAsSheet(new PrivacyControlActivity(PrivacyControlActivity.PRIVACY_RULES_TYPE_BIRTHDAY), params); + }, getResourceProvider()).create()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.Remove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.BirthdayClearTitle)); + builder.setMessage(LocaleController.getString(R.string.BirthdayClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updateBirthday req = new TLRPC.TL_account_updateBirthday(); + if (userFull != null) { + userFull.birthday = null; + userFull.flags2 &=~ 32; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } else if (position == channelRow) { + TLRPC.Chat channel = getMessagesController().getChat(userFull.personal_channel_id); + if (channel != null && ChatObject.getPublicUsername(channel) != null) { + itemOptions.add(R.drawable.msg_copy, getString(R.string.ProfileChannelCopy), () -> { + AndroidUtilities.addToClipboard("https://" + getMessagesController().linkPrefix + "/" + ChatObject.getPublicUsername(channel)); + }); + } + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileChannelChange), () -> { + presentFragment(new UserInfoActivity()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.Remove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.ProfileChannelClearTitle)); + builder.setMessage(LocaleController.getString(R.string.ProfileChannelClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updatePersonalChannel req = new TLRPC.TL_account_updatePersonalChannel(); + if (userFull != null) { + userFull.personal_channel_id = 0; + userFull.personal_channel_message = 0; + userFull.flags2 &=~ 64; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } + + if (itemOptions.getItemsCount() <= 0) { + return false; + } + + itemOptions.show(); + + return true; + } + + private void updateItemsUsername() { + if (!myProfile) return; + TLRPC.User user = getMessagesController().getUser(userId); + if (user == null) { + return; + } + final boolean hasUsername = UserObject.getPublicUsername(user) != null; + setUsernameItem.setIcon(hasUsername ? R.drawable.menu_username_change : R.drawable.menu_username_set); + setUsernameItem.setText(hasUsername ? getString(R.string.ProfileUsernameEdit) : getString(R.string.ProfileUsernameSet)); + linkItem.setVisibility(UserObject.getPublicUsername(user) != null ? View.VISIBLE : View.GONE); + } + + private void updateEditColorIcon() { + if (getContext() == null || editColorItem == null) return; + if (getUserConfig().isPremium()) { + editColorItem.setIcon(R.drawable.menu_profile_colors); + } else { + Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.menu_profile_colors_locked); + icon.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); + Drawable lockIcon = ContextCompat.getDrawable(getContext(), R.drawable.msg_gallery_locked2); + lockIcon.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(icon, lockIcon, dp(1), -dp(1)) { + @Override + public void setColorFilter(ColorFilter colorFilter) {} + }; + editColorItem.setIcon(combinedDrawable); + } + } + } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java index cfd1f41c5..787574f04 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java @@ -233,7 +233,7 @@ public class ProfileBirthdayEffect extends View { return null; } final int age; - if ((userInfo.birthday.flags & 1) != 0) { + if (userInfo != null && userInfo.birthday != null && (userInfo.birthday.flags & 1) != 0) { age = Period.between(LocalDate.of(userInfo.birthday.year, userInfo.birthday.month, userInfo.birthday.day), LocalDate.now()).getYears(); } else { age = 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 07429a045..b0d251b50 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -229,7 +229,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi customResetShadowRow = -1; } - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId, false, false); if (addingException) { notificationsEnabled = !defaultEnabled; } else { @@ -242,7 +242,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi if (hasOverride) { notificationsEnabled = true; } else { - notificationsEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); + notificationsEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId, false, false); } } else if (value == 1) { notificationsEnabled = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java index 7a3b363b1..7b8be2431 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java @@ -170,6 +170,7 @@ public class ReportAdBottomSheet extends BottomSheet { } } } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultAdsHidden) { + MessagesController.getInstance(currentAccount).disableAds(false); if (listener != null) { listener.onHidden(); dismiss(); @@ -382,7 +383,6 @@ public class ReportAdBottomSheet extends BottomSheet { for (int i = 0; i < option.options.size(); i++) { UItem buttonItem = new UItem(UniversalAdapter.VIEW_TYPE_RIGHT_ICON_TEXT, false); buttonItem.text = option.options.get(i).text; - buttonItem.backgroundKey = Theme.key_dialogBackground; buttonItem.iconResId = R.drawable.msg_arrowright; buttonItem.id = i; items.add(buttonItem); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java index 0e03a10a6..b5049de77 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java @@ -8,6 +8,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.Activity; import android.app.Dialog; +import android.app.Notification; import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; @@ -72,6 +73,7 @@ import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; +import org.telegram.messenger.EmojiData; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; @@ -220,6 +222,22 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } + public void setSelectedReactions(ArrayList emojis) { + selectedReactions.clear(); + for (String emoji : emojis) { + selectedReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji)); + } + if (emojiGridView != null) { + for (int i = 0; i < emojiGridView.getChildCount(); i++) { + if (emojiGridView.getChildAt(i) instanceof ImageViewEmoji) { + ImageViewEmoji imageViewEmoji = (ImageViewEmoji) emojiGridView.getChildAt(i); + imageViewEmoji.setViewSelected(selectedReactions.contains(imageViewEmoji.reaction), true); + } + } + emojiGridView.invalidate(); + } + } + public void setForUser(boolean forUser) { this.forUser = forUser; updateRows(false, false); @@ -402,7 +420,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private boolean recentExpanded = false; private ArrayList recent = new ArrayList<>(); private ArrayList recentStickers = new ArrayList<>(); - private ArrayList standardEmojis = new ArrayList<>(); + private ArrayList standardEmojis = new ArrayList<>(); private ArrayList topReactions = new ArrayList<>(); private ArrayList recentReactions = new ArrayList<>(); private ArrayList defaultStatuses = new ArrayList<>(); @@ -545,7 +563,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } }; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && type != TYPE_AVATAR_CONSTRUCTOR) { contentView.setOutlineProvider(new ViewOutlineProvider() { private final Rect rect = new Rect(); @@ -838,7 +856,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati TextView emptyViewText = new TextView(context); if (type == TYPE_AVATAR_CONSTRUCTOR) { emptyViewText.setText(LocaleController.getString("NoEmojiOrStickersFound", R.string.NoEmojiOrStickersFound)); - } else if (type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_TOP || type == TYPE_TAGS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { + } else if (type == TYPE_EMOJI_STATUS || type == TYPE_STICKER_SET_EMOJI || type == TYPE_EMOJI_STATUS_TOP || type == TYPE_TAGS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { emptyViewText.setText(LocaleController.getString("NoEmojiFound", R.string.NoEmojiFound)); } else if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { emptyViewText.setText(LocaleController.getString("NoReactionsFound", R.string.NoReactionsFound)); @@ -1010,7 +1028,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati RecyclerListView.OnItemClickListener onItemClick = (view, position) -> { if (view instanceof ImageViewEmoji) { ImageViewEmoji viewEmoji = (ImageViewEmoji) view; - if (viewEmoji.isDefaultReaction) { + if (viewEmoji.isDefaultReaction || type == TYPE_STICKER_SET_EMOJI) { incrementHintUse(); onReactionClick(viewEmoji, viewEmoji.reaction); } else if (viewEmoji.isStaticIcon && viewEmoji.document != null) { @@ -1674,6 +1692,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati lastSearchKeyboardLanguage = newLanguage; AndroidUtilities.runOnUIThread(searchRunnable = () -> { final LinkedHashSet documentIds = new LinkedHashSet<>(); + final LinkedHashSet emojis = new LinkedHashSet<>(); final HashMap availableReactions = MediaDataController.getInstance(currentAccount).getReactionsMap(); final ArrayList reactions = new ArrayList<>(); final boolean queryFullyConsistsOfEmojis = Emoji.fullyConsistsOfEmojis(query); @@ -1723,6 +1742,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati for (long documentId : documentIds) { searchResult.add(ReactionsLayoutInBubble.VisibleReaction.fromCustomEmoji(documentId)); } + for (String emoji : emojis) { + searchResult.add(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji)); + } searchSets.addAll(sets); for (ArrayList array : emojiArrays) { stickersSearchResult.addAll(array); @@ -1731,24 +1753,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati }); if (type == TYPE_STICKER_SET_EMOJI) { - final TLRPC.TL_messages_stickerSet[] restrictedSet = new TLRPC.TL_messages_stickerSet[] { null }; - final TLRPC.TL_messages_stickerSet[] staticSet = new TLRPC.TL_messages_stickerSet[] { null }; - - final Utilities.Callback loadSets = next -> { -// TLRPC.TL_inputStickerSetShortName inputStickerSetShortName = new TLRPC.TL_inputStickerSetShortName(); -// inputStickerSetShortName.short_name = "RestrictedEmoji"; -// MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSetShortName, 0, false, set -> { -// restrictedSet[0] = set; -// if (staticSet[0] != null) next.run(); -// }); - TLRPC.TL_inputStickerSetShortName inputStickerSetShortName2 = new TLRPC.TL_inputStickerSetShortName(); - inputStickerSetShortName2.short_name = "StaticEmoji"; - MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSetShortName2, 0, false, set -> { - staticSet[0] = set; -// if (restrictedSet[0] != null) - next.run(); - }); - }; final Utilities.Callback search = next -> { MediaDataController.getInstance(currentAccount).getEmojiSuggestions( lastSearchKeyboardLanguage, query, false, @@ -1758,26 +1762,19 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (result.get(i).emoji.startsWith("animated_")) { continue; } - String emoji = result.get(i).emoji; - TLRPC.Document document; - document = findSticker(restrictedSet[0], emoji); - if (document == null) { - document = findSticker(staticSet[0], emoji); - } - if (document != null) { - AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).putDocument(document); - documentIds.add(document.id); + String emoji = Emoji.fixEmoji(result.get(i).emoji); + if (Emoji.getEmojiDrawable(emoji) == null) { + continue; } + emojis.add(emoji); } - } catch (Exception ignore) { - } + } catch (Exception ignore) {} next.run(); }, null, false, false, false, 0 ); }; - - Utilities.doCallbacks(loadSets, search, applySearch); + Utilities.doCallbacks(search, applySearch); } else { final Utilities.Callback searchCategories = next -> { if (queryFullyConsistsOfEmojis) { @@ -2044,7 +2041,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati return VIEW_TYPE_EMOJI; } if (position > emojiStartRow && position - emojiStartRow - 1 < searchResult.size()) { - if (searchResult.get(position - emojiStartRow - 1).documentId != 0) { + if (type == TYPE_STICKER_SET_EMOJI || searchResult.get(position - emojiStartRow - 1).documentId != 0) { return VIEW_TYPE_EMOJI; } } @@ -2097,10 +2094,13 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } imageView.imageReceiver.setParentView(emojiSearchGridView); imageView.reaction = currentReaction; + imageView.isFirstReactions = false; imageView.setViewSelected(selectedReactions.contains(currentReaction), false); imageView.notDraw = false; imageView.invalidate(); - if (currentReaction.emojicon != null) { + if (type == TYPE_STICKER_SET_EMOJI) { + imageView.setDrawable(Emoji.getEmojiDrawable(currentReaction.emojicon)); + } else if (currentReaction.emojicon != null) { imageView.isDefaultReaction = true; TLRPC.TL_availableReaction reaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(currentReaction.emojicon); if (reaction != null) { @@ -2151,7 +2151,17 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati Long documentId = null; TLRPC.Document document = null; if (searchResult != null && position >= 0 && position < searchResult.size()) { - documentId = searchResult.get(position).documentId; + ReactionsLayoutInBubble.VisibleReaction visibleReaction = searchResult.get(position); + if (visibleReaction.documentId == 0) { + selected = selectedReactions.contains(visibleReaction); + imageView.reaction = visibleReaction; + imageView.isFirstReactions = true; + imageView.setDrawable(Emoji.getEmojiDrawable(visibleReaction.emojicon)); + imageView.setViewSelected(selected, false); + return; + } else { + documentId = visibleReaction.documentId; + } } else if (searchSets != null && (position - setsStartRow) >= 0 && (position - setsStartRow) < searchSets.size()) { document = searchSets.get(position - setsStartRow); if (document instanceof SetTitleDocument) { @@ -2389,14 +2399,14 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } if (position == recentReactionsSectionRow) { header.setText(LocaleController.getString("RecentlyUsed", R.string.RecentlyUsed), false); - if (type == TYPE_AVATAR_CONSTRUCTOR) { +// if (type == TYPE_AVATAR_CONSTRUCTOR) { header.closeIcon.setVisibility(View.GONE); - } else { - header.closeIcon.setVisibility(View.VISIBLE); - header.closeIcon.setOnClickListener((view) -> { - clearRecent(); - }); - } +// } else { +// header.closeIcon.setVisibility(View.VISIBLE); +// header.closeIcon.setOnClickListener((view) -> { +// clearRecent(); +// }); +// } return; } header.closeIcon.setVisibility(View.GONE); @@ -2424,7 +2434,17 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati currentReaction = topReactions.get(index); } + if (type == TYPE_STICKER_SET_EMOJI) { + imageView.notDraw = false; + imageView.isFirstReactions = true; + imageView.reaction = currentReaction; + imageView.setDrawable(Emoji.getEmojiDrawable(currentReaction.emojicon)); + imageView.setViewSelected(selectedReactions.contains(currentReaction), false); + return; + } + imageView.createImageReceiver(emojiGridView); + imageView.isFirstReactions = true; imageView.reaction = currentReaction; imageView.setViewSelected(selectedReactions.contains(currentReaction), false); imageView.notDraw = false; @@ -2540,7 +2560,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati recentSize = recent.size() > recentmaxlen && !recentExpanded ? recentmaxlen : recent.size() + (includeEmpty ? 1 : 0); } boolean selected = false; - imageView.setDrawable(null); if (includeEmpty && position == (searchRow != -1 ? 1 : 0) + (longtapHintRow != -1 ? 1 : 0)) { selected = selectedDocumentIds.contains(null); imageView.empty = true; @@ -2553,8 +2572,14 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } else if (type == TYPE_STICKER_SET_EMOJI && position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) < standardEmojis.size()) { int pos = position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) - (includeEmpty ? 1 : 0); - TLRPC.Document document = standardEmojis.get(pos); - imageView.setSticker(document, emojiGridView); + String emoji = standardEmojis.get(pos); + imageView.notDraw = false; + imageView.isFirstReactions = false; + imageView.reaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji); + imageView.setDrawable(Emoji.getEmojiDrawable(emoji)); + selected = selectedReactions.contains(imageView.reaction); + imageView.setViewSelected(selected, false); + return; } else if (position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) < recentSize) { int resentPosition = position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) - (includeEmpty ? 1 : 0); if (type == TYPE_AVATAR_CONSTRUCTOR && showStickers) { @@ -2923,6 +2948,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public ImageReceiver imageReceiverToDraw; public boolean isDefaultReaction; public ReactionsLayoutInBubble.VisibleReaction reaction; + public boolean isFirstReactions; public Drawable drawable; public Rect drawableBounds; public float bigReactionSelectedProgress; @@ -3584,20 +3610,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } if (type == TYPE_STICKER_SET_EMOJI) { -// TLRPC.TL_inputStickerSetShortName inputStickerSetShortName = new TLRPC.TL_inputStickerSetShortName(); -// inputStickerSetShortName.short_name = "RestrictedEmoji"; -// TLRPC.TL_messages_stickerSet restrictedSet = mediaDataController.getStickerSet(inputStickerSetShortName, 0, false); - - TLRPC.TL_inputStickerSetShortName inputStickerSetShortName2 = new TLRPC.TL_inputStickerSetShortName(); - inputStickerSetShortName2.short_name = "StaticEmoji"; - TLRPC.TL_messages_stickerSet staticSet = mediaDataController.getStickerSet(inputStickerSetShortName2, 0, false); - - TLRPC.TL_messages_stickerSet baseSet = staticSet; // staticSet != null ? staticSet : restrictedSet; - - if (baseSet != null) { - for (TLRPC.Document d : baseSet.documents) { - standardEmojis.add(d); - rowHashCodes.add(43223 + 13L * d.id); + for (String[] section : EmojiData.dataColored) { + for (String emoji : section) { + standardEmojis.add(emoji); + rowHashCodes.add(13334 + 322L * emoji.hashCode()); totalCount++; } } @@ -4099,7 +4115,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati skewAlpha = .25f + .75f * skewAlpha; } } - boolean drawInUi = skewAlpha < 1 || isAnimating() || imageViewEmojis.size() <= 4 || !lite || enterAnimationInProgress() || type == TYPE_AVATAR_CONSTRUCTOR || type == TYPE_CHAT_REACTIONS; + boolean drawInUi = type == TYPE_STICKER_SET_EMOJI || skewAlpha < 1 || isAnimating() || imageViewEmojis.size() <= 4 || !lite || enterAnimationInProgress() || type == TYPE_AVATAR_CONSTRUCTOR || type == TYPE_CHAT_REACTIONS; if (!drawInUi) { boolean animatedExpandIn = animateExpandStartTime > 0 && (SystemClock.elapsedRealtime() - animateExpandStartTime) < animateExpandDuration(); for (int i = 0; i < imageViewEmojis.size(); i++) { @@ -4308,6 +4324,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } float scale = imageView.getScaleX(); + if (type == TYPE_STICKER_SET_EMOJI) { + scale *= .87f; + } if (imageView.pressedProgress != 0 || imageView.selected) { scale *= 0.8f + 0.2f * (1f - ((imageView.selected && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR) ? 0.7f : imageView.pressedProgress)); } @@ -4343,7 +4362,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati drawable.setAlpha(255); } else if (!imageView.isDefaultReaction && !imageView.isStaticIcon) { AnimatedEmojiSpan span = imageView.span; - if (span == null || imageView.notDraw) { + if (span == null && type != TYPE_STICKER_SET_EMOJI || imageView.notDraw) { continue; } drawable = imageView.drawable; @@ -4366,7 +4385,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati //scale here only selected emoji canvas.scale(0.85f, 0.85f, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); } - if (type == TYPE_CHAT_REACTIONS) { + if (type == TYPE_CHAT_REACTIONS || type == TYPE_STICKER_SET_EMOJI) { canvas.scale(scale, scale, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); } else { skew(canvas, i, imageView.getHeight()); @@ -4484,6 +4503,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentEmojiStatusesUpdate); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.groupStickersDidLoad); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); if (scrimDrawable != null) { scrimDrawable.setSecondParent(this); @@ -4499,6 +4519,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentEmojiStatusesUpdate); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.groupStickersDidLoad); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); if (scrimDrawable != null) { scrimDrawable.setSecondParent(null); @@ -4528,6 +4549,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati updateRowsDelayed(); } else if (id == NotificationCenter.groupStickersDidLoad) { updateRowsDelayed(); + } else if (id == NotificationCenter.emojiLoaded) { + AndroidUtilities.forEachViews(emojiGridView, View::invalidate); + if (emojiGridView != null) { + emojiGridView.invalidate(); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java index 45749e361..a3ca6f18e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -317,6 +317,10 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter } + public void openStoryForCell(StoryCell cell) { + openStoryForCell(cell, false); + } + private void openStoryForCell(StoryCell cell, boolean overscroll) { if (cell == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java index 6b4c7ac13..b39c25999 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -1787,7 +1787,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (stealthModeIsActive) { StealthModeAlert.showStealthModeEnabledBulletin(); } else { - StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), resourcesProvider); + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), StealthModeAlert.TYPE_FROM_STORIES, resourcesProvider); delegate.showDialog(stealthModeAlert); } if (popupMenu != null) { @@ -1808,7 +1808,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica }; ActionBarMenuSubItem item2 = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_stories_stealth2, LocaleController.getString(R.string.StealthModeButton), false, resourcesProvider); item2.setOnClickListener(v -> { - StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), resourcesProvider); + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), StealthModeAlert.TYPE_FROM_STORIES, resourcesProvider); delegate.showDialog(stealthModeAlert); if (popupMenu != null) { popupMenu.dismiss(); @@ -2031,7 +2031,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (storyHolder != null) { HashSet ids = new HashSet<>(); ArrayList inputStickerSets = new ArrayList<>(); - if (storyHolder.storyItem.media_areas != null) { + if (storyHolder.storyItem != null && storyHolder.storyItem.media_areas != null) { for (int i = 0; i < storyHolder.storyItem.media_areas.size(); ++i) { TL_stories.MediaArea mediaArea = storyHolder.storyItem.media_areas.get(i); if (mediaArea instanceof TL_stories.TL_mediaAreaSuggestedReaction && mediaArea.reaction instanceof TLRPC.TL_reactionCustomEmoji) { @@ -3616,6 +3616,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica selectedPosition = 0; } updatePosition(); + if (storyViewer != null) { + storyViewer.checkSelfStoriesView(); + } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (DialogInterface.OnClickListener) (dialog, which) -> { dialog.dismiss(); @@ -4025,7 +4028,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica final boolean sameId = getStoryId(currentStory.storyItem, currentStory.uploadingStory) == getStoryId(oldStoryItem, oldUploadingStory) || oldUploadingStory != null && currentStory.storyItem != null && TextUtils.equals(oldUploadingStory.path, currentStory.storyItem.attachPath); - final boolean animateSubtitle = sameId && (isEditing != wasEditing || isUploading != wasUploading || isFailed != wasFailed); + boolean animateSubtitle = sameId && (isEditing != wasEditing || isUploading != wasUploading || isFailed != wasFailed); boolean storyChanged = false; if (!( @@ -4058,15 +4061,16 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (storyChanged || oldUploadingStory != null && currentStory.uploadingStory == null) { headerView.setOnSubtitleClick(null); + CharSequence subtitle = null; if (currentStory.uploadingStory != null) { if (currentStory.uploadingStory.failed) { - headerView.setSubtitle(LocaleController.getString("FailedToUploadStory", R.string.FailedToUploadStory), animateSubtitle); + subtitle = LocaleController.getString("FailedToUploadStory", R.string.FailedToUploadStory); } else { - headerView.setSubtitle(StoriesUtilities.getUploadingStr(headerView.subtitleView[0], false, isEditing), animateSubtitle); + subtitle = StoriesUtilities.getUploadingStr(headerView.subtitleView[0], false, isEditing); } } else if (currentStory.storyItem != null) { if (currentStory.storyItem.date == -1) { - headerView.setSubtitle(LocaleController.getString("CachedStory", R.string.CachedStory)); + subtitle = LocaleController.getString("CachedStory", R.string.CachedStory); } else if (currentStory.getReply() != null) { StoryCaptionView.Reply reply = currentStory.getReply(); @@ -4122,7 +4126,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica dot.setSpan(dotDividerSpan, 0, dot.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.append(" ").append(dot).append(" ").append(LocaleController.formatShortDate(currentStory.storyItem.date)); - headerView.setSubtitle(ssb, false); + subtitle = ssb; + animateSubtitle = false; } else if (isGroup && currentStory.storyItem != null && currentStory.storyItem.from_id != null) { SpannableStringBuilder ssb = new SpannableStringBuilder(); AvatarSpan avatar = new AvatarSpan(headerView.subtitleView[0], currentAccount, 15); @@ -4158,7 +4163,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica dot.setSpan(dotDividerSpan, 0, dot.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.append(" ").append(dot).append(" ").append(LocaleController.formatShortDate(currentStory.storyItem.date)); - headerView.setSubtitle(ssb, false); + subtitle = ssb; + animateSubtitle = false; } else { CharSequence string = LocaleController.formatStoryDate(currentStory.storyItem.date); if (currentStory.storyItem.edited) { @@ -4170,9 +4176,21 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica spannableStringBuilder.append(LocaleController.getString("EditedMessage", R.string.EditedMessage)); string = spannableStringBuilder; } - headerView.setSubtitle(string, animateSubtitle); + subtitle = string; } } + if (subtitle != null) { + if (storyViewer != null && storyViewer.storiesList != null && currentStory.storyItem != null && storyViewer.storiesList.isPinned(currentStory.storyItem.id)) { + if (!(subtitle instanceof SpannableStringBuilder)) { + subtitle = new SpannableStringBuilder(subtitle); + } + + SpannableString pin = new SpannableString("p "); + pin.setSpan(new ColoredImageSpan(R.drawable.msg_pin_mini), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + ((SpannableStringBuilder) subtitle).insert(0, pin); + } + headerView.setSubtitle(subtitle, animateSubtitle); + } if (privacyHint != null) { privacyHint.hide(false); } @@ -4946,7 +4964,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica emojiAnimationsOverlay.setAccount(currentAccount); if (reactionsContainerLayout != null) { reactionsContainerLayout.setCurrentAccount(currentAccount); - reactionsContainerLayout.setMessage(null, null); + reactionsContainerLayout.setMessage(null, null, true); } if (likesReactionLayout != null) { likesReactionLayout.setCurrentAccount(currentAccount); @@ -6474,7 +6492,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica delegate.requestAdjust(false); } }); - reactionsContainerLayout.setMessage(null, null); + reactionsContainerLayout.setMessage(null, null, true); } reactionsContainerLayout.setFragment(LaunchActivity.getLastFragment()); reactionsContainerLayout.setHint(LocaleController.getString(isGroup ? R.string.StoryGroupReactionsHint : R.string.StoryReactionsHint)); @@ -6610,7 +6628,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica return false; } }); - likesReactionLayout.setMessage(null, null); + likesReactionLayout.setMessage(null, null, true); } else { bringChildToFront(likesReactionLayout); likesReactionLayout.reset(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java index 7aa350978..72360b29b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java @@ -334,6 +334,10 @@ public abstract class SelfStoriesPreviewView extends View { } else { scrollToPositionInLayout = position; } + + for (int i = 0; i < lastDrawnImageReceivers.size(); i++) { + lastDrawnImageReceivers.get(i).onBind(lastDrawnImageReceivers.get(i).position); + } } public int getClosestPosition() { @@ -412,6 +416,7 @@ public abstract class SelfStoriesPreviewView extends View { } void onBind(int position) { + if (position < 0 || position >= storyItems.size()) return; storyItem = storyItems.get(position); if (isAttachedToWindow) { receiver.onAttachedToWindow(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java index b1ec27305..ca09f49e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java @@ -41,6 +41,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; @@ -520,6 +521,9 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente this.storyItem = storyItem; updateViewsVisibility(); updateViewState(false); + if (storyItem != null && storyItem.storyItem != null) { + NotificationsController.getInstance(currentAccount).processSeenStoryReactions(dialogId, storyItem.storyItem.id); + } } private void updateViewsVisibility() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java index 5c750bb23..8c8a29f9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java @@ -39,11 +39,21 @@ import java.util.Locale; public class StealthModeAlert extends BottomSheet { - private final PremiumButtonView button; - boolean stealthModeIsActive; + public interface Listener { + void onButtonClicked(boolean isStealthModeEnabled); + } - public StealthModeAlert(Context context, float topOffset, Theme.ResourcesProvider resourcesProvider) { + public static final int TYPE_FROM_STORIES = 0; + public static final int TYPE_FROM_DIALOGS = 1; + + private final PremiumButtonView button; + private boolean stealthModeIsActive; + private int type; + private Listener listener; + + public StealthModeAlert(Context context, float topOffset, int type, Theme.ResourcesProvider resourcesProvider) { super(context, false, resourcesProvider); + this.type = type; FrameLayout frameLayout = new FrameLayout(getContext()) { @Override protected void onAttachedToWindow() { @@ -142,6 +152,9 @@ public class StealthModeAlert extends BottomSheet { } else { if (stealthModeIsActive) { dismiss(); + if (listener != null) { + listener.onButtonClicked(false); + } return; } StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); @@ -160,9 +173,17 @@ public class StealthModeAlert extends BottomSheet { })); containerView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); dismiss(); - showStealthModeEnabledBulletin(); + if (type == TYPE_FROM_STORIES) { + showStealthModeEnabledBulletin(); + } + if (listener != null) { + listener.onButtonClicked(true); + } } else if (stealthModeIsActive) { dismiss(); + if (listener != null) { + listener.onButtonClicked(false); + } } else { BulletinFactory factory = BulletinFactory.of(container, resourcesProvider); if (factory != null) { @@ -175,6 +196,10 @@ public class StealthModeAlert extends BottomSheet { }); } + public void setListener(Listener listener) { + this.listener = listener; + } + public static void showStealthModeEnabledBulletin() { BaseFragment fragment = LaunchActivity.getLastFragment(); BulletinFactory factory; @@ -205,7 +230,11 @@ public class StealthModeAlert extends BottomSheet { button.setOverlayText(LocaleController.getString("StealthModeIsActive", R.string.StealthModeIsActive), true, animated); button.overlayTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); } else if (stealthMode == null || ConnectionsManager.getInstance(currentAccount).getCurrentTime() > stealthMode.cooldown_until_date) { - button.setOverlayText(LocaleController.getString("EnableStealthMode", R.string.EnableStealthMode), true, animated); + if (type == TYPE_FROM_STORIES) { + button.setOverlayText(LocaleController.getString("EnableStealthMode", R.string.EnableStealthMode), true, animated); + } else if (type == TYPE_FROM_DIALOGS) { + button.setOverlayText(LocaleController.getString(R.string.EnableStealthModeAndOpenStory), true, animated); + } button.overlayTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); } else { long timeLeft = stealthMode.cooldown_until_date - ConnectionsManager.getInstance(currentAccount).getCurrentTime(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java index 502a9407f..29174f170 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -937,7 +937,7 @@ public class StoriesController { if (newStory instanceof TL_stories.TL_storyItemDeleted) { FileLog.d("StoriesController story is not found, but already deleted storyId=" + newStory.id); } else { - FileLog.d(" StoriesController add new story for full peer storyId=" + newStory.id); + FileLog.d("StoriesController add new story for full peer storyId=" + newStory.id); peerStories.stories.add(newStory); } } @@ -1149,6 +1149,31 @@ public class StoriesController { } req.id.add(storyItem.id); } + if (dialogId >= 0) { + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); + if (userFull != null && userFull.stories != null) { + stories = userFull.stories; + } + } else { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId); + if (chatFull != null && chatFull.stories != null) { + stories = chatFull.stories; + } + } + for (int i = 0; i < storyItems.size(); ++i) { + TL_stories.StoryItem storyItem = storyItems.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { + continue; + } + if (stories != null) { + for (int j = 0; j < stories.stories.size(); j++) { + if (stories.stories.get(j).id == storyItem.id) { + stories.stories.remove(j); + break; + } + } + } + } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { AndroidUtilities.runOnUIThread(this::invalidateStoryLimit); }); @@ -2369,6 +2394,7 @@ public class StoriesController { public final long dialogId; public final int type; + public final ArrayList pinnedIds = new ArrayList<>(); public final HashMap> groupedByDay = new HashMap<>(); public final ArrayList messageObjects = new ArrayList<>(); @@ -2415,9 +2441,19 @@ public class StoriesController { private void fill(ArrayList arrayList, boolean showPhotos, boolean showVideos) { tempArr.clear(); + if (type == TYPE_PINNED) { + for (int id : pinnedIds) { + MessageObject msg = messageObjectsMap.get(id); + if (filter(msg, showPhotos, showVideos)) { + tempArr.add(msg); + } + } + } int minId = Integer.MAX_VALUE; for (int id : loadedObjects) { MessageObject msg = messageObjectsMap.get(id); + if (type == TYPE_PINNED && pinnedIds.contains(id)) + continue; if (filter(msg, showPhotos, showVideos)) { tempArr.add(msg); } @@ -2429,6 +2465,8 @@ public class StoriesController { Iterator i = cachedObjects.iterator(); while (i.hasNext() && (totalCount == -1 || tempArr.size() < totalCount)) { int id = i.next(); + if (type == TYPE_PINNED && pinnedIds.contains(id)) + continue; if (minId == Integer.MAX_VALUE || id < minId) { MessageObject msg = messageObjectsMap.get(id); if (filter(msg, showPhotos, showVideos)) { @@ -2472,6 +2510,7 @@ public class StoriesController { final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); storage.getStorageQueue().postRunnable(() -> { SQLiteCursor cursor = null; + ArrayList pins = new ArrayList<>(); HashSet seen = new HashSet<>(); HashSet loadUserIds = new HashSet<>(); HashSet loadChatIds = new HashSet<>(); @@ -2480,7 +2519,7 @@ public class StoriesController { final ArrayList loadedChats = new ArrayList<>(); try { SQLiteDatabase database = storage.getDatabase(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, seen FROM profile_stories WHERE dialog_id = %d AND type = %d ORDER BY story_id DESC", dialogId, type)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, seen, pin FROM profile_stories WHERE dialog_id = %d AND type = %d ORDER BY story_id DESC", dialogId, type)); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -2524,6 +2563,10 @@ public class StoriesController { if (cursor.intValue(1) == 1) { seen.add(storyItem.id); } + int pinIndex = cursor.intValue(2); + if (pinIndex > 0) { + pins.add(Utilities.clamp(pinIndex, pins.size() - 1, 0), storyItem.id); + } } } cursor.dispose(); @@ -2545,6 +2588,10 @@ public class StoriesController { AndroidUtilities.runOnUIThread(() -> { FileLog.d("StoriesList "+type+"{"+ dialogId +"} preloadCache {" + storyItemMessageIds(cacheResult) + "}"); + + pinnedIds.clear(); + pinnedIds.addAll(pins); + preloading = false; MessagesController.getInstance(currentAccount).putUsers(loadedUsers, true); MessagesController.getInstance(currentAccount).putChats(loadedChats, true); @@ -2593,9 +2640,10 @@ public class StoriesController { cachedObjects.remove(storyId); } loadedObjects.remove(storyId); + pinnedIds.remove((Object) storyId); if (messageObject != null) { long id = day(messageObject); - SortedSet group = groupedByDay.get(id); + Collection group = groupedByDay.get(id); if (group != null) { group.remove(storyId); if (group.isEmpty()) { @@ -2620,18 +2668,25 @@ public class StoriesController { return year * 10000L + month * 100L + day; } - public SortedSet getStoryDayGroup(MessageObject messageObject) { - return groupedByDay.get(day(messageObject)); - } - public ArrayList> getDays() { final ArrayList keys = new ArrayList<>(groupedByDay.keySet()); Collections.sort(keys, (a, b) -> (int) (b - a)); final ArrayList> days = new ArrayList<>(); + if (type == TYPE_PINNED && !pinnedIds.isEmpty()) { + days.add(new ArrayList<>(pinnedIds)); + } for (Long key : keys) { TreeSet storyIds = groupedByDay.get(key); if (storyIds != null) { - days.add(new ArrayList<>(storyIds)); + ArrayList ids = new ArrayList<>(storyIds); + if (type == TYPE_PINNED && !pinnedIds.isEmpty()) { + for (int id : pinnedIds) { + ids.remove((Object) id); + } + } + if (!ids.isEmpty()) { + days.add(ids); + } } } return days; @@ -2670,6 +2725,7 @@ public class StoriesController { saving = true; final ArrayList toSave = new ArrayList<>(); + final ArrayList pinnedIds = new ArrayList<>(this.pinnedIds); fill(toSave, true, true); final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); @@ -2679,7 +2735,7 @@ public class StoriesController { try { SQLiteDatabase database = storage.getDatabase(); database.executeFast(String.format(Locale.US, "DELETE FROM profile_stories WHERE dialog_id = %d AND type = %d", dialogId, type)).stepThis().dispose(); - state = database.executeFast("REPLACE INTO profile_stories VALUES(?, ?, ?, ?, ?)"); + state = database.executeFast("REPLACE INTO profile_stories VALUES(?, ?, ?, ?, ?, ?)"); for (int i = 0; i < toSave.size(); ++i) { MessageObject messageObject = toSave.get(i); @@ -2697,6 +2753,7 @@ public class StoriesController { state.bindByteBuffer(3, data); state.bindInteger(4, type); state.bindInteger(5, seenStories.contains(storyItem.id) ? 1 : 0); + state.bindInteger(6, 1 + pinnedIds.indexOf(storyItem.id)); state.step(); data.reuse(); } @@ -2807,11 +2864,14 @@ public class StoriesController { TL_stories.TL_stories_stories stories = (TL_stories.TL_stories_stories) response; for (int i = 0; i < stories.stories.size(); ++i) { TL_stories.StoryItem storyItem = stories.stories.get(i); - newMessageObjects.add(toMessageObject(storyItem)); + newMessageObjects.add(toMessageObject(storyItem, stories)); } AndroidUtilities.runOnUIThread(() -> { FileLog.d("StoriesList " + type + "{"+ dialogId +"} loaded {" + storyItemMessageIds(newMessageObjects) + "}"); + pinnedIds.clear(); + pinnedIds.addAll(stories.pinned_to_top); + MessagesController.getInstance(currentAccount).putUsers(stories.users, false); MessagesController.getInstance(currentAccount).putChats(stories.chats, false); MessagesStorage.getInstance(currentAccount).putUsersAndChats(stories.users, stories.chats, true, true); @@ -2955,7 +3015,7 @@ public class StoriesController { } } else { FileLog.d("StoriesList put story " + storyItem.id); - pushObject(toMessageObject(storyItem), false); + pushObject(toMessageObject(storyItem, null), false); if (totalCount != -1) { totalCount++; } @@ -2964,7 +3024,7 @@ public class StoriesController { MessageObject messageObject = messageObjectsMap.get(storyItem.id); if (messageObject == null || !equal(messageObject.storyItem, storyItem)) { FileLog.d("StoriesList update story " + storyItem.id); - messageObjectsMap.put(storyItem.id, toMessageObject(storyItem)); + messageObjectsMap.put(storyItem.id, toMessageObject(storyItem, null)); changed = true; } } @@ -2994,7 +3054,7 @@ public class StoriesController { ); } - private MessageObject toMessageObject(TL_stories.StoryItem storyItem) { + private MessageObject toMessageObject(TL_stories.StoryItem storyItem, TL_stories.TL_stories_stories stories) { storyItem.dialogId = dialogId; storyItem.messageId = storyItem.id; MessageObject msg = new MessageObject(currentAccount, storyItem); @@ -3028,6 +3088,86 @@ public class StoriesController { return messageObjects.size(); } } + + public boolean isPinned(int storyId) { + if (type != TYPE_PINNED) return false; + return pinnedIds.contains(storyId); + } + + public boolean updatePinned(ArrayList ids, boolean pin) { + ArrayList newPinnedOrder = new ArrayList<>(pinnedIds); + for (int i = ids.size() - 1; i >= 0; --i) { + int id = ids.get(i); + if (pin && !newPinnedOrder.contains(id)) + newPinnedOrder.add(0, id); + else if (!pin && newPinnedOrder.contains(id)) + newPinnedOrder.remove((Object) id); + } + + final int limit = MessagesController.getInstance(currentAccount).storiesPinnedToTopCountMax; + boolean hitLimit = newPinnedOrder.size() > limit; + if (hitLimit) { + return true; +// newPinnedOrder.subList(limit, newPinnedOrder.size()).clear(); + } + + boolean changed = pinnedIds.size() != newPinnedOrder.size(); + if (!changed) { + for (int i = 0; i < pinnedIds.size(); ++i) { + if (pinnedIds.get(i) != newPinnedOrder.get(i)) { + changed = true; + break; + } + } + } + + if (changed) { + pinnedIds.clear(); + pinnedIds.addAll(newPinnedOrder); + fill(true); + TL_stories.TL_togglePinnedToTop req = new TL_stories.TL_togglePinnedToTop(); + req.id.addAll(pinnedIds); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + + })); + } + + return hitLimit; + } + + public void updatePinnedOrder(ArrayList ids, boolean apply) { + ArrayList newPinnedOrder = new ArrayList<>(ids); + + final int limit = MessagesController.getInstance(currentAccount).storiesPinnedToTopCountMax; + boolean hitLimit = newPinnedOrder.size() > limit; + if (hitLimit) { + newPinnedOrder.subList(limit, newPinnedOrder.size()).clear(); + } + + boolean changed = pinnedIds.size() != newPinnedOrder.size(); + if (!changed) { + for (int i = 0; i < pinnedIds.size(); ++i) { + if (pinnedIds.get(i) != newPinnedOrder.get(i)) { + changed = true; + break; + } + } + } + + pinnedIds.clear(); + pinnedIds.addAll(newPinnedOrder); + fill(false); + + if (apply) { + TL_stories.TL_togglePinnedToTop req = new TL_stories.TL_togglePinnedToTop(); + req.id.addAll(pinnedIds); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + + })); + } + } } private final Comparator peerStoriesComparator = (o1, o2) -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java index 9be11843e..c2700e77f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -194,6 +194,7 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { holder.drawAbove = (canvas, bounds, alpha, opening) -> { cell.drawDuration(canvas, bounds, alpha); cell.drawViews(canvas, bounds, alpha); + cell.drawPrivacy(canvas, bounds, alpha); if (fastScroll != null && fastScroll.isVisible && fastScroll.getVisibility() == View.VISIBLE) { canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); canvas.translate(loc[0], loc[1]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java index abf0fc448..0600c14e0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -1710,7 +1710,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } } - private void checkSelfStoriesView() { + public void checkSelfStoriesView() { if (selfStoryViewsView == null) { selfStoryViewsView = new SelfStoryViewsView(containerView.getContext(), this); containerView.addView(selfStoryViewsView, 0); @@ -2140,6 +2140,11 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } } + private boolean showViewsAfterOpening; + public void showViewsAfterOpening() { + showViewsAfterOpening = true; + } + private void startOpenAnimation() { updateTransitionParams(); progressToOpen = 0f; @@ -2189,7 +2194,10 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat peerStoriesView.updatePosition(); } - if (!SharedConfig.storiesIntroShown) { + if (showViewsAfterOpening) { + showViewsAfterOpening = false; + openViews(); + } else if (!SharedConfig.storiesIntroShown) { if (storiesIntro == null) { storiesIntro = new StoriesIntro(containerView.getContext(), windowView); storiesIntro.setAlpha(0f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java index e991d8081..d048ea672 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java @@ -100,6 +100,10 @@ public class StoryWidgetsImageDecorator extends ImageReceiver.Decorator { } public void draw(Canvas canvas, ImageReceiver imageReceiver, float alpha) { + if (!imageHolder.isLoaded()) { + return; + } + float x = (float) (imageX + imageW * mediaArea.coordinates.x / 100); float y = (float) (imageY + imageH * mediaArea.coordinates.y / 100); float w = (float) (imageW * mediaArea.coordinates.w / 100); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java index b9e47e91e..9ba4057fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java @@ -60,7 +60,6 @@ public class ButtonWithCounterView extends FrameLayout implements Loadable { ScaleStateListAnimator.apply(this, .02f, 1.2f); rippleView = new View(context); - rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); addView(rippleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (filled) { @@ -77,14 +76,12 @@ public class ButtonWithCounterView extends FrameLayout implements Loadable { if (filled) { text.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); } - text.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); text.setGravity(Gravity.CENTER_HORIZONTAL); subText = new AnimatedTextView.AnimatedTextDrawable(true, true, false); subText.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT); subText.setCallback(this); subText.setTextSize(dp(12)); - subText.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); subText.setGravity(Gravity.CENTER_HORIZONTAL); countText = new AnimatedTextView.AnimatedTextDrawable(false, false, true); @@ -92,11 +89,15 @@ public class ButtonWithCounterView extends FrameLayout implements Loadable { countText.setCallback(this); countText.setTextSize(dp(12)); countText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - countText.setTextColor(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider)); countText.setText(""); countText.setGravity(Gravity.CENTER_HORIZONTAL); setWillNotDraw(false); + updateColors(); + } + + public void disableRippleView() { + removeView(rippleView); } public void setColor(int color) { @@ -106,7 +107,11 @@ public class ButtonWithCounterView extends FrameLayout implements Loadable { } public void updateColors() { - rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); + if (filled) { + rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); + } else { + rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), .10f), 8, 8)); + } text.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); subText.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); countText.setTextColor(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider)); @@ -523,4 +528,9 @@ public class ButtonWithCounterView extends FrameLayout implements Loadable { public void setGlobalAlpha(float v) { globalAlpha = ((int) (v * 255)); } + + public boolean wrapContentDynamic; + public void wrapContentDynamic() { + wrapContentDynamic = true; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java index 1b689d2b7..975d73d46 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java @@ -382,6 +382,10 @@ public class DownloadButton extends ImageView { private float doneLayoutWidth, doneLayoutLeft; public PreparingVideoToast(Context context) { + this(context, LocaleController.getString(R.string.PreparingSticker)); + } + + public PreparingVideoToast(Context context, String text) { super(context); dimPaint.setColor(0x5a000000); @@ -401,7 +405,7 @@ public class DownloadButton extends ImageView { textPaint.setTextSize(dp(14)); textPaint2.setTextSize(dpf2(14.66f)); - preparingLayout = new StaticLayout(LocaleController.getString("PreparingVideo"), textPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1f, 0, false); + preparingLayout = new StaticLayout(text, textPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1f, 0, false); preparingLayoutWidth = preparingLayout.getLineCount() > 0 ? preparingLayout.getLineWidth(0) : 0; preparingLayoutLeft = preparingLayout.getLineCount() > 0 ? preparingLayout.getLineLeft(0) : 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java index bef5fd6e3..0cc09275f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java @@ -1,5 +1,6 @@ package org.telegram.ui.Stories.recorder; +import static org.telegram.messenger.AndroidUtilities.TYPEFACE_COURIER_NEW_BOLD; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.dpf2; import static org.telegram.messenger.AndroidUtilities.lerp; @@ -29,7 +30,6 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedValue; @@ -46,7 +46,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; @@ -55,7 +54,6 @@ import androidx.recyclerview.widget.LinearSmoothScrollerCustom; import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -84,7 +82,6 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.StickerSetNameCell; import org.telegram.ui.Components.AnimatedEmojiDrawable; -import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.BackupImageView; @@ -92,6 +89,7 @@ import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ButtonBounce; import org.telegram.ui.Components.CloseProgressDrawable2; +import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.DrawingInBackgroundThreadDrawable; import org.telegram.ui.Components.EditTextBoldCursor; @@ -111,6 +109,7 @@ import org.telegram.ui.Components.StickerCategoriesListView; import org.telegram.ui.Components.ViewPagerFixed; import org.telegram.ui.ContentPreviewViewer; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.NewContactBottomSheet; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.SelectAnimatedEmojiDialog; import org.telegram.ui.Stories.StoryReactionWidgetBackground; @@ -136,6 +135,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private int categoryIndex = -1; public final TLRPC.Document widgets = new TLRPC.Document() {}; + public final TLRPC.Document plus = new TLRPC.Document() {}; abstract class IPage extends FrameLayout { public int currentType; @@ -227,6 +227,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. EmojiBottomSheet.this.categoryIndex = category; adapter.updateItems(query); }); + searchField.checkCategoriesView(PAGE_TYPE_GIFS, false); addView(searchField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP)); } @@ -576,6 +577,13 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. return; } TLRPC.Document document = position >= adapter.documents.size() ? null : adapter.documents.get(position); + if (document == plus) { + if (onPlusSelected != null) { + onPlusSelected.run(); + } + dismiss(); + return; + } long documentId = position >= adapter.documentIds.size() ? 0L : adapter.documentIds.get(position); if (document == null && view instanceof EmojiListView.EmojiImageView && ((EmojiListView.EmojiImageView) view).drawable != null) { document = ((EmojiListView.EmojiImageView) view).drawable.getDocument(); @@ -587,7 +595,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. return; } if (onDocumentSelected != null) { - onDocumentSelected.run(null, document, false); + onDocumentSelected.run(document != null ? adapter.setByDocumentId.get(document.id) : null, document, false); } dismiss(); }); @@ -743,23 +751,28 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. searchField.ignoreTextChange = true; searchField.editText.setText(""); searchField.ignoreTextChange = false; - searchField.categoriesListView.selectCategory(categoryIndex); - searchField.categoriesListView.scrollToSelected(); - StickerCategoriesListView.EmojiCategory category = searchField.categoriesListView.getSelectedCategory(); - if (category != null) { - adapter.query = searchField.categoriesListView.getSelectedCategory().emojis; - AndroidUtilities.cancelRunOnUIThread(adapter.searchRunnable); - AndroidUtilities.runOnUIThread(adapter.searchRunnable); + if (searchField.categoriesListView != null) { + searchField.categoriesListView.selectCategory(categoryIndex); + searchField.categoriesListView.scrollToSelected(); + StickerCategoriesListView.EmojiCategory category = searchField.categoriesListView.getSelectedCategory(); + if (category != null) { + adapter.query = searchField.categoriesListView.getSelectedCategory().emojis; + AndroidUtilities.cancelRunOnUIThread(adapter.searchRunnable); + AndroidUtilities.runOnUIThread(adapter.searchRunnable); + } } } else if (!TextUtils.isEmpty(query)) { searchField.editText.setText(query); - searchField.categoriesListView.selectCategory(null); - searchField.categoriesListView.scrollToStart(); + if (searchField.categoriesListView != null) { + searchField.categoriesListView.selectCategory(null); + searchField.categoriesListView.scrollToStart(); + } AndroidUtilities.cancelRunOnUIThread(adapter.searchRunnable); AndroidUtilities.runOnUIThread(adapter.searchRunnable); } else { searchField.clear(); } + searchField.checkCategoriesView(type, greeting); MediaDataController.getInstance(currentAccount).checkStickers(type == PAGE_TYPE_EMOJI ? MediaDataController.TYPE_EMOJIPACKS : MediaDataController.TYPE_IMAGE); } @@ -779,6 +792,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private int lastAllSetsCount; private final HashMap> allEmojis = new HashMap<>(); private final HashMap> packsBySet = new HashMap<>(); + private final HashMap setByDocumentId = new HashMap<>(); private final ArrayList allStickerSets = new ArrayList<>(); private final ArrayList stickerSets = new ArrayList<>(); @@ -826,6 +840,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. positionToSection.clear(); stickerSets.clear(); allStickerSets.clear(); + setByDocumentId.clear(); itemsCount++; // pan documents.add(null); packs.clear(); @@ -853,6 +868,9 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. recentSet = new TLRPC.TL_messages_stickerSet(); } recentSet.documents = recent; + if (onPlusSelected != null) { + recentSet.documents.add(0, plus); + } recentSet.set = new TLRPC.TL_stickerSet(); recentSet.set.title = LocaleController.getString("RecentStickers", R.string.RecentStickers); stickerSets.add(recentSet); @@ -874,6 +892,12 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. // emoji/stickers documents.addAll(set.documents); itemsCount += set.documents.size(); + Object parentObject = set; + if (set == recentSet) parentObject = "recent"; + else if (set == faveSet) parentObject = "fav"; + for (int j = 0; j < set.documents.size(); ++j) { + setByDocumentId.put(set.documents.get(j).id, parentObject); + } EmojiView.EmojiPack pack = new EmojiView.EmojiPack(); pack.documents = set.documents; @@ -967,6 +991,9 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. // emoji/stickers documents.addAll(set.documents); itemsCount += set.documents.size(); + for (int k = 0; k < set.documents.size(); ++k) { + setByDocumentId.put(set.documents.get(k).id, set); + } EmojiView.EmojiPack pack = new EmojiView.EmojiPack(); pack.documents = set.documents; @@ -1029,8 +1056,28 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private HashSet searchDocumentIds = new HashSet<>(); private final Runnable searchRunnable = () -> { - final String thisQuery = query; final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); + final String thisQuery = query; + if ("premium".equalsIgnoreCase(thisQuery)) { + ArrayList premiumStickers = mediaDataController.getRecentStickers(MediaDataController.TYPE_PREMIUM_STICKERS); + itemsCount = 0; + documents.clear(); + documentIds.clear(); + positionToSection.clear(); + stickerSets.clear(); + itemsCount++; // pan + documents.add(null); + documentIds.add(0L); + documents.addAll(premiumStickers); + itemsCount += premiumStickers.size(); + activeQuery = query; + notifyDataSetChanged(); + + listView.scrollToPosition(0, 0); + searchField.showProgress(false); + tabsStrip.showSelected(false); + return; + } String[] lang = AndroidUtilities.getCurrentKeyboardLanguage(); if (lastLang == null || !Arrays.equals(lang, lastLang)) { MediaDataController.getInstance(currentAccount).fetchNewEmojiKeywords(lang); @@ -1173,21 +1220,33 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. } } else if (viewType == VIEW_TYPE_EMOJI) { final TLRPC.Document document = position >= documents.size() ? null : documents.get(position); + EmojiListView.EmojiImageView imageView = (EmojiListView.EmojiImageView) holder.itemView; + if (document == plus) { + imageView.setSticker(null); + Drawable circle = Theme.createRoundRectDrawable(dp(28), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelIcon), .12f)); + Drawable drawable = getResources().getDrawable(R.drawable.filled_add_sticker).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_emojiPanelIcon), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); + combinedDrawable.setCustomSize(dp(56), dp(56)); + combinedDrawable.setIconSize(dp(24), dp(24)); + combinedDrawable.setCenter(true); + imageView.setDrawable(combinedDrawable); + return; + } final long documentId = position >= documentIds.size() ? 0L : documentIds.get(position); if (document == null && documentId == 0) { return; } - EmojiListView.EmojiImageView imageView = (EmojiListView.EmojiImageView) holder.itemView; if (currentType == PAGE_TYPE_EMOJI) { if (document != null) { imageView.setSticker(null); - imageView.setEmoji(document); + imageView.setEmoji(document, currentType == PAGE_TYPE_STICKERS); } else { imageView.setSticker(null); - imageView.setEmojiId(documentId); + imageView.setEmojiId(documentId, currentType == PAGE_TYPE_STICKERS); } } else { - imageView.setEmoji(null); + imageView.setEmoji(null, currentType == PAGE_TYPE_STICKERS); imageView.setSticker(document); } } else if (viewType == VIEW_TYPE_NOT_FOUND) { @@ -1318,16 +1377,18 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private TabsView tabsView; private float maxPadding = -1; private final boolean onlyStickers; + private final boolean greeting; // private final GestureDetector gestureDetector; private boolean wasKeyboardVisible; public static int savedPosition = 1; - public EmojiBottomSheet(Context context, boolean onlyStickers, Theme.ResourcesProvider resourcesProvider) { + public EmojiBottomSheet(Context context, boolean onlyStickers, Theme.ResourcesProvider resourcesProvider, boolean greeting) { super(context, true, resourcesProvider); this.onlyStickers = onlyStickers; + this.greeting = greeting; useSmoothKeyboard = true; fixNavigationBar(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); @@ -1410,6 +1471,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. MediaDataController.getInstance(currentAccount).checkStickers(MediaDataController.TYPE_IMAGE); MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_IMAGE, false, true, false); MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_FAVE, false, true, false); + MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_PREMIUM_STICKERS, false, true, false); } public void closeKeyboard() { @@ -1594,12 +1656,26 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. return (int) (containerView.getMeasuredHeight() - viewPager.getY()); } - private Utilities.Callback3 onDocumentSelected; - public EmojiBottomSheet whenDocumentSelected(Utilities.Callback3 listener) { + private Utilities.Callback3Return onDocumentSelected; + private Runnable onPlusSelected; + public EmojiBottomSheet whenDocumentSelected(Utilities.Callback3Return listener) { this.onDocumentSelected = listener; return this; } private Utilities.Callback onWidgetSelected; + + public EmojiBottomSheet whenPlusSelected(Runnable listener) { + this.onPlusSelected = listener; + View[] pages = viewPager.getViewPages(); + for (int i = 0; i < pages.length; ++i) { + View view = pages[i]; + if (view instanceof Page) { + Page page = (Page) view; + page.adapter.update(); + } + } + return this; + } public EmojiBottomSheet whenWidgetSelected(Utilities.Callback listener) { this.onWidgetSelected = listener; View[] pages = viewPager.getViewPages(); @@ -1625,8 +1701,8 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. public boolean emoji; private final int currentAccount = UserConfig.selectedAccount; - private final EmojiListView listView; public AnimatedEmojiDrawable drawable; + private final EmojiListView listView; public ImageReceiver imageReceiver; private long documentId; @@ -1641,7 +1717,25 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. this.listView = parent; } - public void setEmoji(TLRPC.Document document) { + public void setDrawable(Drawable drawable) { + if (this.drawable != null) { + this.drawable.removeView(this); + } + this.drawable = null; + documentId = 0; + emoji = false; + if (imageReceiver == null) { + imageReceiver = new ImageReceiver(); + imageReceiver.setLayerNum(7); + imageReceiver.setAspectFit(true); + if (attached) { + imageReceiver.onAttachedToWindow(); + } + } + imageReceiver.setImageBitmap(drawable); + } + + public void setEmoji(TLRPC.Document document, boolean isSticker) { if (documentId == (document == null ? 0 : document.id)) { return; } @@ -1651,7 +1745,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. if (document != null) { emoji = true; documentId = document.id; - drawable = AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, document); + drawable = AnimatedEmojiDrawable.make(currentAccount, getCacheType(isSticker), document); if (attached) { drawable.addView(this); } @@ -1667,7 +1761,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. listView.invalidate(); } - public void setEmojiId(long documentId) { + public void setEmojiId(long documentId, boolean isSticker) { if (this.documentId == documentId) { return; } @@ -1677,7 +1771,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. if (documentId != 0) { emoji = true; this.documentId = documentId; - drawable = AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, documentId); + drawable = AnimatedEmojiDrawable.make(currentAccount, getCacheType(isSticker), documentId); if (attached) { drawable.addView(this); } @@ -1721,6 +1815,9 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. if ("video/webm".equals(document.mime_type)) { filter += "_" + ImageLoader.AUTOPLAY_FILTER; } + if (!LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_KEYBOARD)) { + filter += "_firstframe"; + } // if (svgThumb != null) { // svgThumb.overrideWidthAndHeight(512, 512); // } @@ -2189,7 +2286,9 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private final FrameLayout inputBox; private final EditTextBoldCursor editText; - private final StickerCategoriesListView categoriesListView; + private int categoriesListViewType = -1; + @Nullable + private StickerCategoriesListView categoriesListView; private boolean clearVisible; private final ImageView clear; @@ -2304,70 +2403,6 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. } }); - categoriesListView = new StickerCategoriesListView(context, null, StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { - @Override - public void selectCategory(int categoryIndex) { - super.selectCategory(categoryIndex); -// if (type == 1 && emojiTabs != null) { -// emojiTabs.showSelected(categoriesListView.getSelectedCategory() == null); -// } else if (type == 0 && stickersTab != null) { -// stickersTab.showSelected(categoriesListView.getSelectedCategory() == null); -// } - updateButton(); - } - - @Override - protected boolean isTabIconsAnimationEnabled(boolean loaded) { - return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS); - } - }; - categoriesListView.setDontOccupyWidth((int) (editText.getPaint().measureText(editText.getHint() + "")) + dp(16)); - categoriesListView.setOnScrollIntoOccupiedWidth(scrolled -> { - editText.animate().cancel(); - editText.setTranslationX(-Math.max(0, scrolled)); -// showInputBoxGradient(scrolled > 0); - updateButton(); - }); -// categoriesListView.setOnTouchListener(new OnTouchListener() { -// @Override -// public boolean onTouch(View v, MotionEvent event) { -//// if (event.getAction() == MotionEvent.ACTION_DOWN) { -//// ignorePagerScroll = true; -//// } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { -//// ignorePagerScroll = false; -//// } -// return false; -// } -// }); - categoriesListView.setOnCategoryClick(category -> { -// if (category == recent) { -//// showInputBoxGradient(false); -// categoriesListView.selectCategory(recent); -// gifSearchField.searchEditText.setText(""); -// gifLayoutManager.scrollToPositionWithOffset(0, 0); -// return; -// } else -// if (category == trending) { -//// showInputBoxGradient(false); -// gifSearchField.searchEditText.setText(""); -// gifLayoutManager.scrollToPositionWithOffset(gifAdapter.trendingSectionItem, -dp(4)); -// categoriesListView.selectCategory(trending); -// final ArrayList gifSearchEmojies = MessagesController.getInstance(currentAccount).gifSearchEmojies; -// if (!gifSearchEmojies.isEmpty()) { -// gifSearchPreloader.preload(gifSearchEmojies.get(0)); -// } -// return; -// } - if (categoriesListView.getSelectedCategory() == category) { - categoriesListView.selectCategory(null); - search(null, -1); - } else { - categoriesListView.selectCategory(category); - search(category.emojis, categoriesListView.getCategoryIndex()); - } - }); - box.addView(categoriesListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 36, 0, 0, 0)); - clear = new ImageView(context); clear.setScaleType(ImageView.ScaleType.CENTER); clear.setImageDrawable(new CloseProgressDrawable2(1.25f) { @@ -2389,13 +2424,72 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. searchImageView.setOnClickListener(e -> { if (searchImageDrawable.getIconState() == SearchStateDrawable.State.STATE_BACK) { clear(); - categoriesListView.scrollToStart(); + if (categoriesListView != null) { + categoriesListView.scrollToStart(); + } } else if (searchImageDrawable.getIconState() == SearchStateDrawable.State.STATE_SEARCH) { editText.requestFocus(); } }); } + public void checkCategoriesView(int type, boolean greeting) { + if (categoriesListViewType == type && categoriesListView != null) return; + if (categoriesListView != null) { + box.removeView(categoriesListView); + } + categoriesListView = new StickerCategoriesListView(getContext(), null, type == PAGE_TYPE_STICKERS ? StickerCategoriesListView.CategoriesType.STICKERS : StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { + @Override + public void selectCategory(int categoryIndex) { + super.selectCategory(categoryIndex); + updateButton(); + } + + @Override + protected EmojiCategory[] preprocessCategories(EmojiCategory[] categories) { + if (categories != null && greeting) { + int index = -1; + for (int i = 0; i < categories.length; ++i) { + if (categories[i] != null && categories[i].greeting) { + index = i; + break; + } + } + if (index >= 0) { + EmojiCategory[] newCategories = new EmojiCategory[categories.length]; + newCategories[0] = categories[index]; + for (int i = 1; i < newCategories.length; ++i) { + newCategories[i] = categories[i <= index ? i - 1 : i]; + } + return newCategories; + } + } + return categories; + } + + @Override + protected boolean isTabIconsAnimationEnabled(boolean loaded) { + return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS); + } + }; + categoriesListView.setDontOccupyWidth((int) (editText.getPaint().measureText(editText.getHint() + "")) + dp(16)); + categoriesListView.setOnScrollIntoOccupiedWidth(scrolled -> { + editText.animate().cancel(); + editText.setTranslationX(-Math.max(0, scrolled)); + updateButton(); + }); + categoriesListView.setOnCategoryClick(category -> { + if (categoriesListView.getSelectedCategory() == category) { + categoriesListView.selectCategory(null); + search(null, -1); + } else { + categoriesListView.selectCategory(category); + search(category.emojis, categoriesListView.getCategoryIndex()); + } + }); + box.addView(categoriesListView, Math.max(0, box.getChildCount() - 1), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 36, 0, 0, 0)); + } + private void updateButton() { updateButton(false); } @@ -2412,7 +2506,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private void updateButton(boolean force) { if (!isprogress || editText.length() == 0 && (categoriesListView == null || categoriesListView.getSelectedCategory() == null) || force) { - boolean backButton = editText.length() > 0 || categoriesListView != null && categoriesListView.isCategoriesShown() && (categoriesListView.isScrolledIntoOccupiedWidth() || categoriesListView.getSelectedCategory() != null); + boolean backButton = editText.length() > 0 || categoriesListView != null && categoriesListView.isCategoriesShown() && (categoriesListView != null && categoriesListView.isScrolledIntoOccupiedWidth() || categoriesListView.getSelectedCategory() != null); searchImageDrawable.setIconState(backButton ? SearchStateDrawable.State.STATE_BACK : SearchStateDrawable.State.STATE_SEARCH); isprogress = false; } @@ -2440,7 +2534,9 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private void clear() { editText.setText(""); search(null, -1); - categoriesListView.selectCategory(null); + if (categoriesListView != null) { + categoriesListView.selectCategory(null); + } } } @@ -2900,4 +2996,9 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. } } } + + public static int getCacheType(boolean stickers) { + return LiteMode.isEnabled(stickers ? LiteMode.FLAG_ANIMATED_STICKERS_KEYBOARD : LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) ? + AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW : AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java index e6cfdbe21..e5166101f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java @@ -42,7 +42,6 @@ import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -67,7 +66,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; -import org.telegram.messenger.DialogObject; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; @@ -1479,7 +1477,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai showReactionsLayout(false); } }); - reactionLayout.setMessage(null, null); + reactionLayout.setMessage(null, null, true); } reactionLayout.setFragment(LaunchActivity.getLastFragment()); reactionForEntity = entityView; @@ -1758,7 +1756,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai detectFaces(); } }, 350); - EmojiBottomSheet alert = emojiPopup = new EmojiBottomSheet(getContext(), false, resourcesProvider) { + EmojiBottomSheet alert = emojiPopup = new EmojiBottomSheet(getContext(), false, resourcesProvider, false) { @Override public void onDismissAnimationStart() { super.onDismissAnimationStart(); @@ -1817,6 +1815,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai stickerView.setScale(1.5f); } appearAnimation(stickerView); + return true; }); alert.whenWidgetSelected(widgetId -> { if (widgetId == EmojiBottomSheet.WIDGET_LOCATION) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java index 615b2879d..b87c948de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java @@ -186,6 +186,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private boolean wasSend; private long wasSendPeer = 0; private ClosingViewProvider closingSourceProvider; + private Runnable closeListener; public static StoryRecorder getInstance(Activity activity, int currentAccount) { if (instance != null && (instance.activity != activity || instance.currentAccount != currentAccount)) { @@ -433,6 +434,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } } + public StoryRecorder whenSent(Runnable listener) { + closeListener = listener; + return this; + } + public StoryRecorder closeToWhenSent(ClosingViewProvider closingSourceProvider) { this.closingSourceProvider = closingSourceProvider; return this; @@ -2736,6 +2742,10 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg fromSourceView.show(); fromSourceView = null; } + if (closeListener != null) { + closeListener.run(); + closeListener = null; + } fromSourceView = closingSourceProvider != null ? closingSourceProvider.getView(finalSendAsDialogId) : null; if (fromSourceView != null) { openType = fromSourceView.type; @@ -3044,6 +3054,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } private void startRecording(boolean byLongPress, Runnable whenStarted) { + if (cameraView == null) { + return; + } CameraController.getInstance().recordVideo(cameraView.getCameraSessionObject(), outputFile, false, (thumbPath, duration) -> { if (recordControl != null) { recordControl.stopRecordingLoading(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java index c1d3862e4..12183e006 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java @@ -31,6 +31,8 @@ import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Business.LocationActivity; +import org.telegram.ui.Business.OpeningHoursActivity; import org.telegram.ui.Cells.EditTextCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BottomSheetWithRecyclerListView; @@ -145,16 +147,18 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC private static final int BUTTON_BIRTHDAY = 1; private static final int BUTTON_REMOVE_BIRTHDAY = 2; private static final int BUTTON_CHANNEL = 3; + private static final int BUTTON_HOURS = 4; + private static final int BUTTON_LOCATION = 5; @Override protected void fillItems(ArrayList items, UniversalAdapter adapter) { items.add(UItem.asHeader(getString(R.string.EditProfileName))); items.add(UItem.asCustom(firstNameEdit)); items.add(UItem.asCustom(lastNameEdit)); - items.add(UItem.asShadow(null)); + items.add(UItem.asShadow(-1, null)); items.add(UItem.asHeader(getString(R.string.EditProfileChannel))); items.add(UItem.asButton(BUTTON_CHANNEL, getString(R.string.EditProfileChannelTitle), channel == null ? getString(R.string.EditProfileChannelAdd) : channel.title)); - items.add(UItem.asShadow(null)); + items.add(UItem.asShadow(-2, null)); items.add(UItem.asHeader(getString(R.string.EditProfileBio))); items.add(UItem.asCustom(bioEdit)); items.add(UItem.asShadow(bioInfo)); @@ -184,6 +188,15 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC } } items.add(UItem.asShadow(birthdayInfo)); + if (hadLocation) { + items.add(UItem.asButton(BUTTON_HOURS, R.drawable.menu_premium_clock, getString(R.string.EditProfileHours))); + } + if (hadLocation) { + items.add(UItem.asButton(BUTTON_LOCATION, R.drawable.msg_map, getString(R.string.EditProfileLocation))); + } + if (hadLocation || hadHours) { + items.add(UItem.asShadow(-3, null)); + } } public static String birthdayString(TLRPC.TL_birthday birthday) { @@ -251,6 +264,10 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC // listView.adapter.update(true); // } // })); + } else if (item.id == BUTTON_LOCATION) { + presentFragment(new LocationActivity()); + } else if (item.id == BUTTON_HOURS) { + presentFragment(new OpeningHoursActivity()); } } @@ -295,7 +312,9 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC private TLRPC.TL_birthday birthday; private TLRPC.Chat channel; - private AdminedChannelsFetcher channels = new AdminedChannelsFetcher(currentAccount); + private boolean hadHours, hadLocation; + + private AdminedChannelsFetcher channels = new AdminedChannelsFetcher(currentAccount, true); private boolean valueSet; private void setValue() { @@ -328,6 +347,8 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC currentChannel = 0; channel = null; } + hadHours = userFull.business_work_hours != null; + hadLocation = userFull.business_location != null; checkDone(true); if (listView != null && listView.adapter != null) { @@ -490,14 +511,16 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_NAME); } - private static class AdminedChannelsFetcher { + public static class AdminedChannelsFetcher { public final int currentAccount; - public AdminedChannelsFetcher(int currentAccount) { + public final boolean for_personal; + public AdminedChannelsFetcher(int currentAccount, boolean for_personal) { this.currentAccount = currentAccount; + this.for_personal = for_personal; } public boolean loaded, loading; - public ArrayList chats = new ArrayList<>(); + public final ArrayList chats = new ArrayList<>(); public void invalidate() { loaded = false; @@ -507,7 +530,7 @@ public class UserInfoActivity extends UniversalFragment implements NotificationC if (loaded || loading) return; loading = true; TLRPC.TL_channels_getAdminedPublicChannels req = new TLRPC.TL_channels_getAdminedPublicChannels(); - req.for_personal = true; + req.for_personal = for_personal; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.messages_Chats) { chats.clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java b/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java index 4b6e1c1cb..5970e3de5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java @@ -133,7 +133,9 @@ public class BotBiometry { if (result != null) { try { BiometricPrompt.CryptoObject cryptoObject = result.getCryptoObject(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + if (TextUtils.isEmpty(token)) { + encrypted_token = null; + } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { encrypted_token = token; } else { if (cryptoObject == null) { diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_extend_location.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_extend_location.png new file mode 100644 index 0000000000000000000000000000000000000000..bc79a6ec77db9582812c68028c0eb765c0f0a7d0 GIT binary patch literal 858 zcmV-g1Eu_lP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~#7RU!R9Fe^n7eBgK@`UKiU|@> zqNa#KqG==&#ecv)3IRnM!ABv2m7s-%Sa`w0LJ-ocg%A(}J_^zDs)Z?|-~%EFH#Qb( zVhT}Axc*L@i)UwNW^Z#| zt@ektdV$1ta04`fPZkMGfRRcWG2jAN0-eeViFZIxsl;g54djZ8%3BI|mqvP6Zj7%7$O9ab%XVGc-q2PY>wbq%yYBKf&TK!vpCnz;i4NV{J49%Q zqmgz^X~WV(F-i6I4iVaF4YAE_wnN#Wn521ohX^gG0WS3z4~g%``M9e<`MxVXrG^MK zQ<+)gAg=3>O7*}V#eX%Mp7PA6EM;s|x~;yp9S&Otk3!-p>k<%>M}cqW2(5~@cd(E_ zvy=~+CS@*rIE^!|hNcZ$a{*q zzz8@4g5DY=QVP~<I6~`gjqly6YH`WsQkJei?V4f-#lN{09zf# zArEl-nX%*AUd9-YA|%B$k>4+$^b(NM)TzizHzT>vkgni)ddRff_|9p+(dAqDK9HV+ z#wW`)qrYHn7=4-bk0 kXaF?8Cm_4FE|u=UU)I~w(~CS*F8}}l07*qoM6N<$f+37@L;wH) literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_location_forever.png new file mode 100644 index 0000000000000000000000000000000000000000..68b42e964b13f2c7574c89be66d0b3a108cd6922 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM`*<()^$B+ol zw^OaXnH>d=7k73E<-8G5{1`anP{i$@oNsiGc&&9YNLVA zUc3K?&E;ZgCH}__7ra$B`|SQ>#j`7KJtv*op+8yC@1WKbhqWb&O?5jid;Z~mb4X^% zL*6UfUhnJRI$2`B%yn+~`CnWzUOoK>3|GV&OekNTbEI&GX;b{4ipq`G7z)p*be;b3 zGV=8l(?6RydSf5$-di+deu$vm+od1pINLn*@~P}Pqq2+TN$)>y`)AA3*K*hOl->6h z|I?dpZkBiWt;5QoAEr^(?fGj91J3;6D!eK;bIbNyn#~<|Snl6)Pc!>kyVBBtCwhU} zTl=I>OI9!W+O86&+~>SudX$;s&Gm1^Bdi&>GBs;XHa-z?`*-I@wKGnibMyIDd`+D4 z{>qk&qY~d8#a2ab;D7vI@Tu2M`S~(x_a`!Ytn#xhzU28@;Kh377xQ29-Yr=_{lll2 r70o{bUo^UBoSm;NjTH6;p%3_vwEtS%u=j)?DB3+;{an^LB{Ts5Y&ZlZ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_stop_location.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_stop_location.png new file mode 100644 index 0000000000000000000000000000000000000000..12c43b972153d422e96425c32d92ba920b7d3afe GIT binary patch literal 1048 zcmV+z1n2vSP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0f=NU{R9Fe^m|JMhaTv$$&i*=i0o;YJZzQ6h^h$1)`%$%PoMP(m)akSit8b=l6a7?|=LM-`|#%^*@5|Kq6QUR=c~qN7ErF1$p2F z=m0H=M52qFdSE^sECYo>F6hNz7kC2v;yuD~P#xsutFdvC<9r=noUEDkwV>1K4Wqwk zI0OPeBYEen(T(u2;H9T&+6(D9Igs-~n+iU;QT-xkjLMDKX5GyC2=LVCjnvuFLoNX~ zjqaAq)hkxU;gRbC->C-hVc-F9;{-*n^pFRDtFGwq;p!7BW3byXQMw^+Ag$X(rM8lF?jpG=tv%;e1T+6=K}I|~&$5pK`nZ&(|zdfFMYIuI829KOkH=%lVm z`(o4pvx8BwnqHpY=C(s zt{v)3mQO#&uV2^cnG8C>2QW+5GmS3 SLrHu90000oQc7*`=&m zl}m$;LLx*IUY9OzV}@ea#=J4PjwWQ?wd0&UyPx*M|M~r&%a{L`=c*@zs;Z)+0sw%j zhdaefLDr^}F^W2J<2+db@SGRb8F(Pnom4cGz#|?%(CL7g!Ycz{N)UkFJW)tTApn2` zAOI-{Zq5X#f43|F^q=26EGGFg0N}G19uz0I9h?I$OJ0v3!iQ_Rkm@JU-_<>KtLHQcv0dr`(vQ^99XX-Z^`=PMD=a?pM@YXBdN$ zfu{pctIJQkEUB`$PL=vpIA2FMe&MVd3EG)`y93bif~yfTD|$8ZX4&ui0M2QK3rC+0c# z7mE`@^YfO5lE5o*mD}p*yr>#WZDu_Vo?EBi)E9-8loD%PEP?!K_&V5TTb7X)oMNd* zHw;maeZzelG^ormVg}er3Go!iehZtQ;}5OV9b3JeR?T)9XQwLl!mOG?lqsQg0~5ZT zjL*T{>UeGK-4tJ$)uL)2O<(jmB{z<5g8CPKTa?2A(w{Fi8<@))eRZhf?hCQ*6QwDm=85#La70n@u2qQB zXk9!In|d^S43#N^_TS*E`h>H?7mlC()mHTtF2ra!&*XhKEYlAu@D3sxg}>eCL0J#Tix&gvu`?lllU=h}d_ z)8ap4G3d)~m=T<%I(tSRTk$1Z7N(c1)7`^42us!xiAG1VC?9O&v)-x2W$a&|!QWD< zaxY}oW>9S|IqQ#w7ARUM#jbiR}+rPmPRUnY~i8HVnn>0 z@2;mroPLx-%4_v3TR!e0B7zpnOLr~7W2S}U+*Mfb^4Xs3c^Wsz6A5kZsX`u)a_6nLzLP8D*x$ayNBpho<$q&PSA|SH|1gp9gdaJu~=S4#MZC=ErnmKQ~ z(#fB;!+mEj3M5;0q(6NR`j33vv*QJRkx%@33r`UwilmfqC%Re_GaHy(GNk$XD6c{N zgJ1u>!F}gv+s#1&Dc$Bm#HL$$e{sBJI3O~S=}>#PWm5*p%IRyNBWG zSTjOi54cmk?10t0s$cpz_kF#f^I_PAZ&}SvMVeS2q+a8fu6OPXzDD^sp6y!HK_6rI zD~Id<e5@B4DH?D z>AdVs*jscXt-txsIQLJu!Qh)nakjTTUf>uiGYIk=z0)>6cSCk0y+$FK7lK5EfYhz?5Pf|p3Ot#y~ z-e_o}R#`kOl9e8*J=UJ(GKO}?rpW@TcF4qXSAtw!GRWu}^X$$NT-Fcws89Pc4w#G) z3|w5P49TDr-mRXPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz197#k$R9FeMn9FMvK@i5XQR4$a zl3>7~7!)-ZPig`QLXx{D1@SNN5AfzqRE!5tBIKkHL4qhK-nq-==D}XVSg1*=!2FRCU!?)jcykHN7ddH7VtCc`K=Xpx1zE`(T(Wl}c~qSXN;X zgJ2xYf+7(|+`*PFilPHx8Z;})9a!?hDAEb0a;x~u_&zuWM!-(6-XL2(#l#Ue6xHf% zYGEYygO@?IAJ}I>Poo9JwH)QTsAhkoH7Yz3M!_eqfW8K{EUHLAR<6}RRYbK%14`P2 zs5|3}`G;7;NSB<5o&?o9A=`YYid@X4XNEA;MqFwg z9nZLV)yR^4hS)yiNnOoU4+e?_ynR6^W5Q9N^5!{S4dR@&0{5%Vhymx6@uW6KC>57t z0qz|z+F!;{Sz&OBF?H>X550KGnC5_J+jO#i>KART(LIk7|^%wmqj|z zf>Wg>0lf+ndmQpGhEgr`T*ErL_N}5#Ql{wcU`qNh|X1P z3OCdkgT$7Z%$;eB{+8Ti1~tba2t8ck$D$eGt%ajU9+NUPzQ+QgPjfLIGN0BkF9Zrd zu5h%OkAi#PD=3oh5N3c5{Of$KP~(q(Tty<7Jbn<FM_7D*=P=9XfPbTc%(w}61<-NT4{k58SDFu1k*Rn#Uc&i9{s~Kxx|~cb2#~85 z;c_0Mu|vM zM8Dbc3&Yj0C|7NzwL(#K^l{+dKFp+uBW~^IO#{oRHpT|H8443E%fIyg117CoV>Aj< QXaE2J07*qoM6N<$f-(#bi~s-t literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_button_erase.png b/TMessagesProj/src/main/res/drawable-hdpi/media_button_erase.png new file mode 100644 index 0000000000000000000000000000000000000000..c10494655fbf31f7f451bedceb8b388043cb573f GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM`S-Pi-V@L$& z+bQS0m<1-f4lRhxqh9O8ZR~0-)UU6D(s?KRQ_M%h8s@&9*-ntx3IPD zJYb{Pc{6;~y_0|61k7kNxHQw?lhZ?)=D-a$0j7zc9CSGr2dw8Yn>1guD^J<>z_&9i ze(tH6B68w@&AH;BBMkT~@cIf$;yO zZx2^2sOC56DLwjL_SfD?m&)AEYSujRwL8&nm2aG_cxGp;|F@or&euJh7O-uzD6UL! zO7>Yl;h1jo#Ou9&lV-p6;aHr^?Uk&2HAnjQ^GROp fUhMyB*zFk2o=kPozyEp_DCj+1{an^LB{Ts5n&QS9 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-hdpi/media_button_restore.png new file mode 100644 index 0000000000000000000000000000000000000000..66009667d60fad340dcfa71497a9bb0e979bc642 GIT binary patch literal 775 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM315=@=i(^Ox z=i6!Ly+Z;;j?XoeUX$qXtI;4tgwxpi;L)74X|CNF3vO=ZUg)ck+obtLUqDb$TrZ_; zSI)w`mMH&qIf6G{336U?5?Z{%)o*_A_rCML-~C?t*=>U5hlh8n-~Igf^;1p$uU}Qy zb~oPRt;k<+HS2C;=KGV9t^&dB>nB(%bN)ZBlpr$e1N#w|D?Pp_?Mm|r+ixQTy{=G}>V zMAkH%m1!z3%~SC|xNEKO#;qE>CuVnb8qyP9dFlhTy&oC>bviyCcem+OF#4c_b`ax*%-Vwb6Vqlfi&l53S3XF zew2OnY-aBKZLGQ*ryn`AFS+{3o9Ha>BTtrAoG%iyJrX~q`L}}nHH~LKeSIg^q)4xd zxEI{|f~&`;tNTNwDR=QF=A3}-39(J81qX7KyzG?MFPyvnwUe#u^#sYLobJPmc1uVkvq<8GASe-fy85}Sb4q9e0Q0Fw AHvj+t literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-hdpi/media_button_undo.png new file mode 100644 index 0000000000000000000000000000000000000000..6578b283cf0a93a627fd59a0d47c0afb938ec143 GIT binary patch literal 513 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM`S+=K(V@L$& z+i4r~4jBlvc}8j(8Y*dR4VGUZThZik*ZPBvkB{uBV1;RVwGDZ#E1gxZ8EqBic4img zdANC&hk8nM;fd5wp8Ma-DgOTd=hPdSTa#Sa7cpOC+|L|2?dw4fo911qE5)G}AU-XSnrlIqCL76-2*(EC$%$;@1 zd~w^2reEI-W`$avUQx~D`bFmaofs+Ar7S1U2Swkl_1lmflRdfe_v5~E-fvS&b(Gwm zZ!Z5}d6{G77Q?E3zLRVRXS@!1W>dU(@!<(d&$vQ*fANLCWXN)oG1@P`|AFk4@4ppU jk5-l_SP94m6g}WrZ}QhrKOyWADEK{H{an^LB{Ts5ql3h4 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-hdpi/media_sticker_stroke.png new file mode 100644 index 0000000000000000000000000000000000000000..7f7acef8a8a2585923d6c6bfcd104d7cd8cb1599 GIT binary patch literal 1036 zcmV+n1oQieP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0c1c7*R9Fe^m_29|Q4q)PG!fMJ zc|j9D5(s{xg3+L$prS$wJ0pUPSOhEt1zXF2jkSu}1Z@QEEHtJN6p`RZp@;-66f_D^ z3?d>i$@%-AJDaz+Z!de7JF5)*GqW@QH*fB}-PyOvWM-uF3S>)%C!_g%zJaTCz&BjDaEI!)|<9Hp%CMVUQ$>so;WOU+@sWlSd~buLV)}?G!fG4O-CRLREXq? zmsCY3b6hISl+S-dhYwe1FqdvTTfQe%oI5Giiy*KR-DD)Upi!J^VnV+WYN%g3xtEz8 z_7-(gmTs2<*q@A0L#+icQEMoOyFx1DsbIlkO~HCHUIu6`j@xxwp7ATzOwJmbf-iU1~w1;qwV!@*=H1#b!h z|Ft0IYXc^2R#fD%H)oP&v|heCf}|3-dx4G|K3U>8LpyarB-Yb10Mv&%on&4U&M^WH zz#VM8mdXnUM+j*zNYn^!f~n*xgodQN z#5$Y=?Z%6&kU7(6l5K@|9O#AI3dX?)@DTL!iwDt(!g$@tAAw%7t?+-u$dH=AWw1LI ztbrq#uQ4$-1l^31njc{ki*N%JvJKcFzYn|OEp_u2+vME><`(Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0@kvBMR9Fecmq}<;K@f&BCPdtD zIjGSfao-VwLDY-l5+zDNMO3^hc<>;IMDXeYUR*#FK}A7N<{%0xfp{?}DjJDOl(-RN zjG%Gf9lw84J@ic8Bs1@YSny3%cUM){>({T}o4mXpka#>^2J?F$RrC}TvJsr@j-D|> z2CC=_&8`~L8zQ8P7D@rztcV}z8na)Z3!`NY5zVB7;k^}c7+nnCt-UHl%4i`>yxAuI zgdV1B=&RPZFKqTcVFQU9X|YYQSnQqIpG_B-&RK;HWTrZsZI)IB`wdiBU%lzxRTQ$< zZjrBU(FlE^v8b28SyQ)`<(PT_K#wM2|FXwp_;hYatbXZn*kT$7dRvuvc6MlOK3l{zTfBzpyD!0 z@=DS@2;4>A9nfK?m3#|(;2z{6`Xp(Ed{_xLlpC@?a&Y#ao(9@0Am#Sb&T54yK&zw& zpaSZ_$xe-RD|k-7=4v%bB}g83sLsF2iSGkO z#=(Tn9%(%|9{|Z;n4C78(q!D=jx z!h6sg+{rhLn?^Ib%>y%UxJNPe9HSpva-TgkO9pckVrTc6g0s#Hi5|^LIBzy8lqipK z%(P;TV(UdbQEgv>o-&Qs!Vl29E1xS_O|VvK0W5?Wpk$*VeU;2~LIE`(IhM(rF`dBrJ2cvm?arc1VY*$7AX%U8lxc|=86FITLacL@DO=G0C;?a^StaUnR-5{DL&XwP&fi9Hqc>PSpXwYv9BR>fJe zWn8JymF5~q5!0a6yR@6wI{Zo@eKRN1Ys`F-Cq3=qP-HZrC0oGtC60!SNnLgVO0bW> za@S{Cd#455S)^`v4voSd40_2{!$Z*f?Gh{BPR>T`Nw9(TIdtwql6j!lLmOl(@>R?{ ze@5D&o-#j&J{{`ls3VzHbt;Sn{l9l$CcX^ybts;}BjR)}rHl5bp03;J1OKhfg%t)( Z{tvT3DYlrPemnpG002ovPDHLkV1hxW`yv1U literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors.png new file mode 100644 index 0000000000000000000000000000000000000000..377ca4a58f8f9f257cc8620ac5a52bbf1bd92f62 GIT binary patch literal 1137 zcmV-%1djWOP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0+et)0R9Fe^m`g}hQ5eS^O@oMv zh_r;FB+4E{r3r#XEuw`IxTqEdwFn9;q!!U4&?s88ifB>Psznh6LG*yqR!Q`N#H8pY zl}cgnvWMpM`_G)CXJ+obGn2PX^ucewbH3L(bMLw5o|&AS{}Ox!BEjxpZ!{X6NyJo` z3`Ou6x}gi&B9X`!^xqXGQ3Z#f1A^o`&P%Wv#)m#Dik3kWcu5b&Hqa!0cm#aFwi`wb zdtwwRfMYNKRvysU2jx)U4njWyMX(;u!dI};MPr#8pH-XWLbze8p&vqRHbsb^2#4V( zNcx~In;NlLk~Ep;U}ZmzysQhE1afCWyDf&^n{h3IM?#B9{)S$gadJQ)b;f`ex|P)d z;X^K>PuL9fnjufTg>55fA-6)Q>!*JJK0-63JYCqdCheEi`kLeBr?d&E04ph%6~_qB zBW>lJErOxM8jWtSK3C(L1X|#d3$8EM?U?pKqubGq9{ypQ*f6zu?lOg{nbcy>qBxdm z%0_BDgD~R%<6CBHQX>x@nX%4TdxFM!#00b^IQ~+HvFgouZ_$abF&W^M321QVfNc@% zfP@9?#`v|#sf4G{3Ds^K{rO;Jp6kA@m!co{D1Y%S01@%j8PEbaUwE zf}TjpM)}-DJ;ek^(QT$JrLEp>h5$ry&PxCf~7(bUS9b|<7GgrtYSzIZeCd7aN+ zrr(RcW7?UjdIFz;jwD+=l5_ziu{AUz-j011n)YkQmc!)kaXBlnErrYUJ6(UeHt{XQ zlmx_$HoksocS0YGW1P{0ilTSvh){(uI+ucWH@}}y9Oo*K=xyxY%7nNuJB)Km10s65 z-HQ|3?8;-V_{X#`2llGPFgu;`wx`74)JyM^3EGwt5R!rV#c!1d7%j|CN zSHj;;auY~&zpMNshdjj1Rf3V}L!J;?6rBK1OmW@sCF#l%qZg%qe@PnC#b@oO=qz}z z>WDVWt?7yoqhGX=ZU|nm>56&zDXM#KPjxh-H(|L~tZew)^G)#K-LFVGJA;gc^We&D zI(uLN#EuPSLd%_?8R=>d%g;b7Kodz8?OAU?KLY!WQ|mAMTjuo*7-%IN1szGfM3bxZ z%FVk2P%GDWrD(JtViSPoha$M;_{~PifKYrgd@31!V00000NkvXXu0mjf Dg*pVx literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors_locked.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors_locked.png new file mode 100644 index 0000000000000000000000000000000000000000..394cfe2f0e25871558b4d302bb82765ea9fd6b38 GIT binary patch literal 971 zcmV;+12p`JP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0HAzH4R9Fe^m`g}hVHC$5Q-c;3 z5g7?ZMU*9kW(a|WE~1SHZfsFei&j18u`Q@5TDNFX)T%`i6m6oQGzbcz2c#B7K@pi0 zLs_8}TGQ`8erLSS+&eQi-?)el{N|i{&iT$c_c3=qEh+gg*{?t>dpLVEkw~l{V=*j* z1@H|9;XU-lVzFU#afKn8;558}Y_h$mlhC;Vx*{fs+_DdU;JH+=)qtl14C)f#nn#HQz#(ddjOL3*QxDYn1V8Zd-@*V^3iRr5;|TMGwa z(gPgK@ov*>6`0gn103}*<^sd$YKs*^r>+pi7r6!rbbp{(Gqye4v#=WiF>fX(n(R>) zsHiQ3B+j;BblgmS-r@5XXu$|P1aHD12Pmd3Ob>Jh2dZ*iJ~*9J4ELBtjT~%*8ypV= z;~wn8)R+r>sudh)NDd@p+rSWy@C&cPiPln3!$_WtEB8sT4J4xwe6}X#`8=S{B{f9e zLGa=vzuMZ{m@M(xIII?p4p}qwzKk54+K7F1NqaLAJUOUe4HsP>shbdfM+kH(1L^kE zUoTbt_SL{PxD2+%#Y|j>%E(>>JCucJyILQa7!hDiB^(9qGPS?{1ol$JOo_HG`yu?w zSbY-8;U!4A%%87jO?Pr-_{RwD+pr6wuS$9|lH0*#M|wQ!m<6f55cYZ44O^iVbj$2* zA5|jS&tm&?NB6raI&&gIUM-j`orrj_s5%c`x$3*-H;rxb?Vnq#^0ryQs7O8D#= z=w-PlR}pgb7p-IvvOlo7iiO1~s(b$eOnNX{!gA#!w#E|CtE2J?@>6&=TnjXk`2dbU z9h6%G>=rOtZvLWZx@-ask}i5@eS~K)=7M_u{NJ*$Go#UFI12+1CK_&i*xG!2+DHGD t&{S)+$JXXb|6G_4Z{Zf(l{os}kUzBz{K+WJ{`~*|002ovPDHLkV1n}knoR%z literal 0 HcmV?d00001 diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-hdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-hdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-hdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_username_change.png new file mode 100644 index 0000000000000000000000000000000000000000..194c013d7f892c2b3b283e209b95cfcbdc0fb2f4 GIT binary patch literal 966 zcmV;%13CPOP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0FiAu~R9Fe^m^*7!K^(<*4MZcc z5(GsXZMI2c8HDY{!jE8)GLTxk1dJ(z-ypU|QdkAS$|6<@!Fn5spn(+>L=#Lq!K+aC1dre$eA8?;f78wm z6tWC=;4vHp*~oUe_KFDFf_pGU7r`Oi4^&^W6!LA=QW$|&;IAk{hyDh+r;enO3^>$Yr35PKU#&zNfIzMJ9A$ z_B0{)4ASl6l)p!T>c_~=00ugJonW{#P^||jb7kd~+t~^z9Qitv}}u zt&g~#4>?>3!p}Knh0L>kqeAao&fSO$s_>agyb!#rF4xj~DK1ElD?tyg96U3gshmwJ zyBGu~sUnOoht|0VX2{cby~6orkn4IFYg1$I7pa#n4eg~W3Mvdp(uPKz$6hgiKrdfE zC*vh40`3-txPxL=7vrChv^Ys2*NY(kPCHPnYtp??`=^7L&qHE0@8L7(<1SfIXi2X^|H-h)r!Yq$#^!1$Dxa`Xil zwV)nP!U3$hL-GM;A*G1gpRiNcNl~>u@~19F0VqhPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0ib+I4R9Fe^m_KL~K@`SwMuL$D ziXcR^QG{#K*eF4`T1jDR9|R?kR_zinrVKWg60lQk?&;f6_KTCgFK>l5@;tm) zw18~Rr_E^ii7;IhGf+?PFkG^1jGy5w92pqw9OUa_6l+jUoxy4#$S-DtxgFeUiSSk| zdf{m z)4NYtF#91B810Jd^C5;)PPr8`7U*oZ&lcEiEn9oYFQ_19U+Pg8UDRB2-%EZ$`nVGG z!4-q;jO|p+C)6Evik;Bl<|o}~YiD-Iw(m?q@C&C`dnk3N@wYEhdvsxHdsJybsRN6& zprOudube-iJ-%d3<`XhFTuTcv0mDHx#@}wy^d@OdbSL0L_#I}7wVLEq`>TVTPod#) zx|kC%+zfT;9AoV-S8|TRRVXC8#CRFrfqJJMP78<$IM~Zmp9ps7a<16)Dk=5(fu9zh zf>)J@@f8%Na*0C)PEDwfCt(8?^^h>M^qidUlpNd$gZw^}*!bh_Ey8W*c!}`|fwdRq z@|PbdqRx+eouhG&?~#RD(DeNqE{NG<>Yb$ ziPfjnJhx#PXwe)9EWBm?n^KU9U$Bm9orJOfjyV>%Yll7rx_@)Z4=Udn|He}=ZR>gSdJbLwLLDscQ-`IdR@1J)_E z_xV4ZpvX4;jD2^>TF@A z-8F_QmmXYR_{&$1|D5C1k1;`$Cpv3Hm7CO0oPFu+2StV3Nzq}~Gwv_yeCW=*F0)U$ zav5_4XWfeA!~GI_++vxl-YPxnQvUwt#MQ66*rv$#UVh{1_55Lxqj+h~5BBEkEADvR ze)9bGG_}Ik4|e~U*EDh_%wBCC(|p3fBg;E+YrN7GZbS7u0qV>1#BG|&qAz`w_wc=2 zxLG>Xru{vOc*4}np`kyI`Gqmfb8r?G<$A(2uYqs+s?Xvprl!R3KFK@C77=j%smsMj z`&U~$k*ed52<>|{GobzXN!KaSw#z^v zZ1lxbZmhhU57hjW6)t}*wByFgKH*B1X^m^nZDAG+?tI3kvC!A~ugCf+b8@b4>znjC+h{Fui@e!5kFFp00i_>zopr0CPL^O#lD@ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_location_forever.png new file mode 100644 index 0000000000000000000000000000000000000000..9542a68d0fe3e53af8338b63ad0e444117ff7dd0 GIT binary patch literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfOw-fFF~o!S z?Ic5Qr$CY8R}VTYJjld5XHJwIEq~{$lGLqUa6_1*Nr8QNV147XMq>}xr*C?L z1KKTT_!g|1))U{vxW-{yi@Ha&-xIG%vrdOxX|`K&kv-+1keGtBGke;tgtsS-sZCg- zAO3lh@b0wx481;Q>mD4u*ne|>Q>6_y1+`!Mf4W5g}n>FeEkl*xK z==&_c%pzsqw)hssn&vbAXXQoZ%oBNa?TO;cV`tUtSXe*Ud9UuhUcvM~gK59xjM4|S SYM-M(f#>P!=d#Wzp$P!@Mz1FT literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_stop_location.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_stop_location.png new file mode 100644 index 0000000000000000000000000000000000000000..ee5f790adbe3e8965e3828f96b57365e78387e09 GIT binary patch literal 726 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfyu$s#WBQ# zck5JpkMKZ|PCP(0Wol{FzsBF}>TDz1+O&_zBlbF6$b~ zcg@p0yZPo5(`~L&>kjPNGJfc=B+?sfCGyOpv{3$b;#W8GPBjpa(ILcgl4|C;pk zJxbD9iH=v}Pn2ddW`8fa@4H(rxGd_#SJ@e@pFeP}N|2fEwn_T_9qzTKFJ0r^$7F7FRR-iUpTt=KPtui&3fK z$(rx7C+^HLlqmCAGe!8$8uN?k-6@h1e|}Fo;}F1WuPFN|XwL%Ys<~$sU&-t~xS(f& z>_1Djuyw(6t|{7H`LxvArumOTakkS1)-;EiN1Sh8SG=VBf1gnQ-MtH>F0OUi^*Q~3 zdeUpHKMl?N7j{p%|8Dn#>Z2;gH&1`&wcoNecVTh02w!98El`^BboFyt=akR{00omR A*Z=?k literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-mdpi/large_log_actions.png new file mode 100644 index 0000000000000000000000000000000000000000..41e266dd5c6578d700a8e6a4cc44dbb3bcfcc810 GIT binary patch literal 1138 zcmV-&1daQNP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAu9+(|@1RCodHn!RfjQ540qMp3~; zP@`A`F@;T(U_ek5ghc;?bQ&c}3I)YR5XHvAFR&3URm3!DEtM$5MikVD;zy%}l|ckW zA!4%rj?9M5WOnz>%zcyH&0ILVk9qIBd(Y0?c{?*LExF|ioJS6-c=Aw=0w76PPBf_T0ZM>l{8*SyUlC%{jT z#&(AtgKSS4!eFj0r$b@xYHgjK&Ib7agRg^C&Xb}Cc0_bX^+gP;+NH}$XJ%K`QArL$ z+6jID3ws91%90C_r~fB{zb=N)jp!r75v(Swv*g1SZFoD1Rz z&|~3Q8HWPCP}a7rcDjm1lPWWPov$w! z2aL!3f^XP0c&+U$fCfW6PN94KeW1tR^Q}UjkuLE(wX(0rZ?MF;AE` zW?S2CeUzaOrmen4iRnTR literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-mdpi/left_status_profile.png new file mode 100644 index 0000000000000000000000000000000000000000..06e1b645d49df95f741ed0287c935a155de28d5d GIT binary patch literal 808 zcmV+@1K0eCP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR917@z|H1ONa40RR917ytkO0OB=utpET5l1W5CR7ee#mOW?`K^TTz6B3J< zLbxKrRpLQf;}00oI(Ay7wlj@|h_z3jjM%k#W}WCo7I(IEdsxeJf8Ec+UK|5uQB8rI=A z^fF^=rvEuR;xSkTZ4Xvp7Fu9Ttm`wTMzhaY-+>S`;WcP$aI9|!f@*@6B7X(VWFG=P znaO?a>q$``r+q?S2kCwjoN-!`$%#+F)xcD0EMg9#Emz_=Tu^PT5}<)^9OB?=qUjq? z=$%@vv+y)Fz{TpCb9_snJ%9@V>)KLc0N2D^>qU%81DyAjgm@Cawwj2ownO=3BIfQg zXX7Bji(vVvE~I@r`0giS(RV5lGnYAM{PBcp+wG$AyBAs`6>qx{eLoYin5*Rg6G7nd zuiJARe_)Q+&0;Xr=R!XEM_YJ%iwUe+@)Ji`*q3du1@d9OB&@KF5O0s&@ zT-vU0&~ux%HN{~YLN{8Y=k%i6-=;+l9A3GVgGPH8Zo!KXqo|nEaE|sf%C-@R_l+0UUC>;} zp{S{s#4@-E+9IScJ3A6AU)SGhZ$oFh)w7q{=$?R6=Jk-iuEQWr1n)q54_%jEDQ{6# z18+dvf%FF_c0_O(UV`SryCY^{&?nO;KN9l{ED`&S*Z^OoQ^BS)0;;UUzQ7^D0cgG>&ZvkJ$n$Dakf3sBXfjUcIj2>gq zP3H+UliE20PZ(WYq4cx2G&_g$b?4@(#SFgBo(X@8-Qm2aPbOx;LlK8&U41X(blDBg zJ$t4`=COoz)K`8HQFXeeko>W{*xSy%#!p$_z4w#T;hD2Hs+^epEkFM4#A^T6qq0tW94Ne52v>*{OnRYdNatlrLalm(X5%XMc#) c=U;bO;#hYd{_#NGpa~Q%p00i_>zopr080Cf*8l(j literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-mdpi/media_button_restore.png new file mode 100644 index 0000000000000000000000000000000000000000..1150e2b8bb807f4370b0957c03eb065963232319 GIT binary patch literal 567 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfY@w%%V~7Xu z+bOo*%#H$W?_CZ${W;(iFj=WiAxX7EF|4VhYwp}zH@KR5TYDFnnTaK(K9%2a@z^~t zZ&qntrlwYf6$^S9&!<1iHQN48RVGH+;==}G>-T%6=j1)E{6Fy-CyV0+F5%3oussHO z&AB@oVwMJ~XRf$>{jFe^r$j^K-3N`*A2@bb*_*lFc$l?mesk#E#c}Mi&AZ;835<6- zb~9vl#Kn^Cb0m+!L^A?o{%u&vjpY+Tl+B9iR7%K6fU4iFka{i%0CC z#5V=*pws--taDG^(J^IXU+{S9BK~U&j!sh7HhjVKmn&%6V~x(>wX<#7CcZc5zQZpU z*`V9LZqL&i2Ijpb=E-gA*8XLEC7L!TZrZia0_P60?{Lx!-p;e}S)#m`LLuMj2Yak1 zvMbJNs=iR@KGEFildMKlr}?Ddj{mC-4yU=!X$+ij{quFf6LKfi#Xql^>0Np>qVK6r nXmD=Z&KmCLXRq(tKf9j!L-aQ0Z=crcgCfn-)z4*}Q$iB}<%Zxx literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-mdpi/media_button_undo.png new file mode 100644 index 0000000000000000000000000000000000000000..e27bdb34f122d7f3d6b6abb9bcafc0c7e5e4858d GIT binary patch literal 429 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfOx)AOF~o!S z?d08jjE*90<*`m8D@wj7S?Tt=Jd!LashU{9y|sc#-@#K!i)*c$VQTXD{l({ExG|@jNoDBO8vpmbsS2&yAqqHkOw_#z#&fI&C zZ`W*VTrF@|uuatB(7D4k=l?LVEz9hxy3VoV+$-NSjqC#xSid^{cV7_kx?{!ZLlQ0} zU#_XH7OOvB8kARg`9EL8{$7rnL5AanY?`!Q+W%^{h(*D<~6@vd$@?2>`yin~4Ab literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-mdpi/media_sticker_stroke.png new file mode 100644 index 0000000000000000000000000000000000000000..c65e16cd03b4489bd3686e62dd00f3db9160fd1b GIT binary patch literal 750 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfhoe%#WBQ# zckfhx579u8_SzsZPq&qsOAP%5onkvKIjO{^y<_1Hcajd*WpWmO8{@(4cwwqa7xzL} zja?lrS88`3XjN#^4!m&T$RFo#f9gIzGrH7I%JWr+W*1cabb09_BMxu z#gBsCr8N~YRz0wixUKMAo8y#3bhRHvU;{mgMt)KZH zZ1>bKYrq99es<<=zS zX*K&!x0o-uY;5vKeSvNb1M>y0TmufP2W1YotxX=;O$cpCQfoh?^@C@5g3s*&sXxaP z&bwDji!8mfrp%Q$<7Q^>oPFoSt~TsHepz&qc5C=VnMV>CHzQ@sCLVKJu#vs$p7#GD z!LyC}A1-~lGUL;9&rPzqLSH_bd^W9f{`?`n;btM{AIYNCPfFzWvf17WvuNZi`rPxf z*YnpZ_k}^CJ?{@}{qDG~@re9|!1e!y{deVRYHtwUChxN)e8J^V?Tfs34&LAVdi@o9 Y=2GvcdG8bU-v*^MPgg&ebxsLQ02N|A)Bpeg literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_birthday.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_birthday.png new file mode 100644 index 0000000000000000000000000000000000000000..65912197d04aba58e85446b7efea50b1d4e80415 GIT binary patch literal 748 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfho+>#WBQ# zckL8kkB~r-cKwi9y`Jl;m_dck~4ghe;%=BcT-GXz~i zw1fW~X#LUHy@ll<%gh!d@5Lp_lTH5qJG{65_r2K{(<>hwxBNcmzh(ZjyT9{vw(*}% zF}nWXmtE8%Z^=6>*YaH7_pC_yq_D=>KIhQIjIL>k| zjy@bd`^SWj|KI<(>T1AzZJ$7h%S@SmrAcj#OLu4oaOyw)_{03qK}r4{+?f-4oh~-| zrr${X!E5E%?{H1@DPyJiOvcg#|5Ji(qE7Z-W*xj~>##U@s=>|)+_nsb%sdNx4jMn2 z6)@fYW7AV3t6Fu>dd&hKK@-Ia_U8}nRBoOL{gZdi=cC-5X3Mmg6WYrxxV;O`h;CfR z6lq>j$aj|gRdL?EYFCjGEvbj5`+u$0R=U?Do55bqU#tG@jLhxjDt@ygVSjK|($kR1%lr<1 z=vNe#dZQ-bb7;!!&4xdP60bY@uNAjr|Gdw%Nqs@>hVU)xXm7|(`n%iv zo?)p}b;o6crUkM^nVX8T_Su%CRV4Z`_O8_^Sth)JF?j-0`DEcW{!a2WEs_-sb8|iw z)?6!TY~?v&G{o+t|ff(?ZwZV!1IZbX(236dV^mTI8y|bo*oj zmkAWkscCRPG28#Whu@@NA6Q%AQVtR2q zz9}oCP3=Z|-HT@{`8IxBRLSVmV8Uej@oJy*KCU*$Sxwvxu6#uiT)Nd8fwy-LCP(Z6~Qb|s}Z9SKX&XTSE)C9mQC z47F)TE=AbBJGkQ2S*H6Y4%aU|tC(+c{n{L+Sn=k_SdY5anQI=@vt8L8!1MJ3Q<+2h z%e)M&gMJh8S|^1y>^avuOSiFX=EOfDS0bPKJu_1cba2}K)acH$zpvYPI;~`PC|7R`o$;9H<@tEJo;AhNGZSP)-s!o=Z`%9S8~3(nOD{*Y3c&!A3BAX7q|M< z37P!t%WZes-S$!aN5=7@Zy7GYc+vaP`CpT~{E@0U8OQ+&7U);xwl8-VsuxyId==OWq zo_9njQ8I49>-K9mrU}S0L@p0hIM)yxu_a6P$z!$ePbD>)*k^2HKe5{J8=Gd-;q^`) z^KFF<(-K(bEx3}W;NMi2VO;u1E5mfB{`mu(IEK0&dUwN|%(Vc+xrIp(uw*yZlVp#-d_|iE&1-Ni{6LW z33=Zq+im5xK+eqJ8&9?YYw`l~RI99u9?Tr34gXHxUSPeeUGzl%mH+RzmVfiR Vb>yMspXZ=d;OXk;vd$@?2>>@-2fF|O literal 0 HcmV?d00001 diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-mdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-mdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-mdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_username_change.png new file mode 100644 index 0000000000000000000000000000000000000000..3d7bfda3e5b84c46900beb5f7b4e42956544c332 GIT binary patch literal 715 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfyva<#WBQ# zckk5mS;3AX?ZUTP6`B;n0=dLQwur=(K0Fo5?G(RgLih*XP2Vk#_zK?n!S7O#s1R_m z^=*(&(n8kVYozw;TNYQ(da|u^5xd>9JNM@lr#(A2cW3W0`)$uuzE92&|c1tAhKb#et6R&v z_oA(1PUE(?)Q2BzxTOm?j()kC)}B`J4gN9iS#+%S zmh$2V?ky|%q&{+AFf@Fl`}XPLQx6sYy$v;V@8wo*-Ry8cKDKPI7*_Ruc=jLv;YxencT4l}mCEGY;lfw<> qI86L=`TOTH-`Yg?oIX_lwVwI-g2EedX%cFngyiY!=d#Wzp$P!hUNTky literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_username_set.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9abc3216c3a589ea794b2410056bf6ca225568 GIT binary patch literal 740 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfyvL)#WBQ# zck9&s*&>c24exy%q_rIbI3)r^cq1Y+k_9JeC1fWH?%01oWSZG`{u|v1`GPEti^7sb zEjlz7X*P4QF{Fi3X?3cX3QOd7y0X=m|L8BTseYO3OL}ZSEPh(vm-jI@Am-ocmR+Aj zKPkMZ6VCqfPlDkvkH+0gj`t(A^cTq7aJn_+>cTni4#doz+sJ)5$ViWe^|#iXTs^tE z+>_hI&7yPi5>rpssT||{yChKYK>y26*DW{NZ=E_RNBTxhuQ+%7l@(dX7+UL`FKP$G9oLg8sSL{LeP&hD*#2RjlHC6v4=dK5(5z_}=j!=Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NF(Md!>RA>e5nO|s5VI0TzVytW? zrI5KnGrJ%cv^7meyP=3X(aHrkN@$lZL}`*zT%d)~9x#eVhOd7kI@{r!8+d7k&2XJutmGBpEb1e&8}j& z0W9=T!F9mHORje_naoeF|BsOLGH@Qe2R8Wu;Re`N@(M^|G3W#%pb&Y2(dLpAB7wn| zLb49AImOuYNh^e4hrpkZM3M}3VLT`GA_&r!Buk6!E%fQ#37j{BUm#66m&#or;|lOD z&CCto>V-Ycq1pp*mpJf~P&+8bCAaukII9MO#tcnHb60#;|FknSBsg2aTqRd%Bj5^n z3v*qQ=9I~1_R#${nP!kK5|d3tMXO#z>j z!GyMt1e>Dx=;Z6HGfE#aZjG%e;02E5he;#i?>dR@36dFG!Pq@e7u3b{dt-DtmFke*Y5GIbq-)~8^~JA8pfB5cJe0c;5aCzjN|h3%!P>K3!qrC(o6WJ=WvK??$v?oY?r*$TpZVfF;EQ2 zJvum&N68oG)4Kfgr>TO)+z0QfhHK;CYs}-AIXEAwXnzOHeA?;AC#Jj>xQOgF&%m&Y zQ7T;S_c8yTE3OlE8#AeZz4Z&sw3T)tcR=h;f;J#uYc@H{<8qorWw&X89QTUc2*-Sk zM&b8h|Irr2Sx=yiK(nBOyA5VelHZ-2le8I-hMX$fB=SttJpVFRioWhvwPD3Ew-Ntn`NT?n7KXeah tSG)QsIiIBKKnsZ6MoXULR00WS;4gjZAeu=ayk`Ia002ovPDHLkV1k+c{}liL literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_location_forever.png new file mode 100644 index 0000000000000000000000000000000000000000..c79e516943939d0d5132c895df5a63b21af9b3e4 GIT binary patch literal 866 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~ySip>6gB0F2&*5QUU^?UJ;uw;_ z`gZ#6Y|%i0_F`6FuK2*_MS;@XtgNh}Ni`-;9E~Df9U019t-daoXVfcCh&WQBq>{C` zl~M4h5@lE0TcWPzE9}3T%nfdeW&7I%h-HZ-@{!I1* zUj_Rf=6j6q8_Ew@KLB#4ym46S6T3AkcgZ`BoYvG2TxwcVPlX?gX*(t+6rEtbr~Uc| zncn!G|HpT{(A&Xoudt<`M{hHmw zIhRVUh4LHu&1U{IoE@Cux3T8SH}=^NmYc0#v}SFC+2iexqbJWkeMjJRdM@MV*{i}U zmh3PVczsIS>8{iao>%Litz52VSn4@%RtBHa^xg?R(Th7LD(q}_d>dS2X`Cfh`N=eN z_F1hHsxwptq931ED)>A$$xZ21QnN6QoYnzyn%=aONwJhASu^#-%{ z%j?8b^xCJH?z}m9LwenwgA#Hn-?!EUDjyPG(BV1#ztx%#?OhxbW*=yC&AlV0tY$7) zC)5(8mOq8NeP)(GG#~TIHx&-|W>0&UdM+nP{ZRSAdFOVuN~-PM5cfG*`StNcktDVE z!Pghqg-Lf${p-A0%Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NG@JU2LRA>e5nOmqAbr8ordDJvC zlT6E$yj7xR8d>T?Wf>?!N<|M!5~4M{7r?D!eo{WCkwZ~wo&oVPRZb!TS3^PS)B{&#ow*riLSb)JDrXP~80wNu>Q z-ad}>Bye?tOWB@Cu#fF~EiEl)*w$|}za7j5(lpxOj{t4p2xw-1LUIM<{FR`1I5-Hb{Z8Tz za}X2B$-&iaYjmH&KC6)%Q*L5w^7NRY1&POk6P8#*Tn^I{=>*6T#>HPD(X zmh6OQ$CiL(ds~cNE(hhiz!jQAyc~G8nPd;m^?W$Hy<#V~*{d&TU$6rct#@rE!)h9P5dZ0m+aS@Jp`9~&B#yI#3ue5o<^Y@ z4Q^3Q4&jf`0>lr2vx<|tpW$3-xbigHn-U_n&+Gb9K23T8y+9eU$7nI)ncy#AO%^-I zaOacru9~ftc%H5;?IZM|QJ3HFty+*+Zgy|PK0tn$;m#o!^A(r5+FGNKPc!*qvgVE0 zw?Xno>>tUG(oKo)17|?Uj%$7;pAM4(U1Y?buEmLO0^W%IGx-UIdk?wOz_V)K1-g;= zbdaBdXL5f$p!vktgC897Npe#RSDs3ex0d1Qno>UMD{TiAhequ06eo56z`0j1f_Oam zDJ8Hy2ET(!A|JCxiPpq?>Wi;Iu&Xdq|0nLVv*A1X;ui5Nk4G zcTctOyMhgY;+M!bu3B1C`<5oXfcKmatn0#OWMjmZMS>Rt3gR1kAR zL%U#m_%}0R6Nla{Z?dmjhb&x+(!`sQNC)jx_Sg}7ae%#*d{5o4cAo~_fjqa1*j~uj z=*18}2E3~&kKT@XC!`CYf&5k5n?Oki?Erg*rW&#(o(sGYTV8_wG`Du2268{-jT!9z zpRKkFfiVksBeskq11-PSmC5_#1M4 z^P01N3h+kkr}FA**+=8NgOD4(e@r8I6M%dKX?rfFwlar~%XHVo|AcL!n-Tsfus^B) zp6!szi;ESYnLOXqN8|hWnU`1romOgxgT_o1TU(h&Q#pfogN`2!DzCOvpxhZa4+?e? UFXraGE&u=k07*qoM6N<$g1Z@z?EnA( literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-xhdpi/large_log_actions.png new file mode 100644 index 0000000000000000000000000000000000000000..9c80bd1b227dbb20cff66495e5daa715ec0d16d7 GIT binary patch literal 2274 zcmb7`X*ksV8pr>$S;h=XBiWKHL$Wj@F{;6oHN?oycpfGsLOnx<#^gaI`@Tf7M93+- zmZ4N=GFckNHnL@3(kM#~=fyeKd2wEx7vJCK`@8S^y072$yY3hF9cxQtBwP{>007d| zgkZBv+MWdXcF#9wJUVv)3brve1gbts&+J|ZUJj<@3l{*@T`vHDVtfGTUdgT`cLe~D z0uTV%C1@{J0RDHDRsi{r-zzkUhf;Q1SeOzFh#{bbyeqLNFNyb*KDDNTMz?RTdM_P@ z5A@np3z-_0IU9%)IT`Sl59scMa~BUB2-l>ej}lhEHYLLcHp!`lX&F)YkHQWfjz!qpRF#p+uat%?E|K$*?WcT0pJ=wvXaOsj z1G8i+{A0ioV}K^h^@z2skTD}&yq#x$RJ7jPNyo>X`2E+lWJdYa6OQ3qgU;GUsAb%Z z5%Vvt`zcrZv3pk`WIb ze0)5cpjMmrSTv^#Yk5l{GJqDyErd_>|5o}2g0zv~AEh2!qvwK0A^^GFerr<|UvF)Jh%1%67+YqV)%P~|#%I4&OUr~NrVX~(a<`&k+f}hw0dK!$bHz&w$y@im*F7t`RfIxy0GSXO|6??l zN7ILJV%P^oeso{4gK1)xx(fQqA)T30A=@Kz94l8yGpC677X>btc#6n)in<5g-@g2S*To5?3THc;h_Nb zg|NcNp$Wkw>XM(K0{8uVG4yt#!;_>yc z(>)q36t06;R$V(xv`KIXR^oj$L-6n-Okc<)dW-Bn$1IM{Zgq^vm-wMh$4WA<_LDkL zXLx{08Fpws(4SV}*KlbDeo8~>&1zkemzfIhb9aPrwbI)Odokhl$&a_(wkrb5hk^38 zds!@vKhiskGyj74G0&mu?{^p}`5HBYuxIncbjtd4lG={v`{*w4HR#%EZ(&QCL^w#z z9E?xjXaTy5u?_!nR@_c$=>`WW_qy9PD)Hddabh=bOzpLU8+0NoqW0l1AfFpoe$|*& zB^oCu-4fnZQ{%1K=Vr;Z zQlu2Uwq!AzVg3a^fk`jhi*?p}Rzj-SPi~I5ZqN*x2vS}9S1g1!H+$%z9uEMy0(~(cmjtL; z_!8}xzQ=cw9t--zX-8}gfaoe}$(0lw6I}-1$xrcGRXkWzpV=@Y^!nl{ArU4V?=R7Ld}sddTaFVWPNfDMKtgW2Z5bFu>5JktC#Xp3>wQ< z0-xnl*c%+SKTQx$oTa_dgz3MqX88l5)4xOAZpyyy9$2{-ZEw>I^0c0+ec{rCj8|nJ~ z5_dra`a_ZnY;~YD68!hbOI=p!vRx(!p8xfm@P;OBt~v7aX*AnunzNzFco;OP&@-aP z{t^TF{ehSqr2QA;1|?jAtISrYeDxeYuZx@Ze)ntK+2x6O-X;TWEM1w6fzMBVD*C>Y zKS31%Om#0N?ZXPy!z*q$4`*?5mq0~MJn#w9^GORa9y=1eT0A?^sc41PMNWqS9{isJ zvMPc)YKGD(*OI77y`8dnRk8-_9pS+@AAa!}R3Zgw$pCH@KP_BIcjE!w(ovIIX9;H0lSt5Ie*%XkaXL{?z;kWQxH_pQ n-_zFvo(V3YsgVAE6xnjmX16yhn^$&$_x20ZbC!fELlXU;$`cah literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-xhdpi/left_status_profile.png new file mode 100644 index 0000000000000000000000000000000000000000..577e6193430c3d722eb253b2ae9648bf52ab7031 GIT binary patch literal 1738 zcmV;*1~vJKP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NIG)Y83RA>dwnM;gRMHGg+)gTcE z12Oo54WM9PU_f0MA1Gniz=+7G0aqqI7VZFdKxRzXXvD;ohKVoGM8Zs*xWY$thZ_VH z;zGtSA_^p;$q35J_WQeU^_;G*zPIkR9X-iERdwn=kK0wZ9(T&6HcO>anS#q(!8Fj3 zxF4hZ6?|7Nm(M1;|3^W>lR*y{06%~%8HFJ3YB2dfdkTVggCX!cC@QiY1l<$%AOu?i zJ_hZUk8rpo?}L=~K9AiWE$ z^ko_u0*2aQcLV(h7Za$y3#>NO%qo0MCo8*CjbLi(*r(P@6*cGK%?JBImWVSiHIbwf zp56)V_D+;r>#0Pi-C?yuPF# zYBcxpi!3zlU=>a$9rv0}>%*vnRX?}s+9cKhD|UE;UYrsmZDN;<@d4^ryMDiPoO_I-$FZKFwi!aUZ~k?$X5t#}5K4 zx8?DMVF&oeI-q_T906~GcapkvR=%bYJ=)3%{(S3z`U6sSH7WBvLCx_@d>r!pq%{xH zIWuP%~i=>?5McRUi#a`6c!{fRkhOel&%S5_Ja?R3Xn1mpx_mC{YbfL)Snnnd|uk z5D1|pe4B@icBn)&r6Y9M^jEtlxyP#NCHD< z2y}VKT;kxY0$M8d4rx=06)mYhgS}uqxYA`7D(Tl!Z7(!?n|Khqft9`{Qlfyg2*h0A zt-rMTw{$K~iT8qM+X7>wm-T+FbkYGCrYzOv0sL`!nlqmhFvnw+YMl--DaH1Vg zpZT75ilp40=`50fzb8H4uhV|a(a#-d;P}ucrI*!CS(=sepx7_(2gT7c5ZY6gB0F2&*5QUU}EreaSX{| zeLLOW`>=z=vDr!*d`NjJ|5zoR;+%Fa+o4fzzTDOkt+_qg79giL? z;%HKMv7mSVuzXS%I9|v+ zcTsssyVG{ zJy)C5NQ>9mZJ4wp#3A&PzL0fk!iU8<-xlPqxwoNSU$gP_sx$u0^G`&DpRkynA1W57 z%J8Q#Ey3JhYfZGnuiVRzDhy6?Ye=tC%6zr@{7Zhe&!^h2`^a=Nzv90&W#g7tqI;NF zR`mHzF!{=MS5Ml`i+RIb=7_WQPS&^PsQs;eThZ~)ZkFG>F&C%wvt-opRt;{I$~gYbtl*$1?yyPq>kIB1=z-FNr>mdKI;Vst0FU_+R{#J2 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_restore.png new file mode 100644 index 0000000000000000000000000000000000000000..ee2b87758b8c61dc8f1fa6ad819d4bb86d68fc5c GIT binary patch literal 1053 zcmV+&1mgRNP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFhee5nA?j@Q5eAIj4?4| zXiRySOEVtK6KRw}Zeixsi1MOwdGMx~2b3Zn3}wm#UPMVp<_|!;xYZO*Nx9@j2~$RB zYML3B(%|@g$2!_)+k36Ow!LsTU;SE_@4D96d!My;Sy@R+J5btz(hmI7JCMz0Ym0V) z6u%sXTrQy8WpHA*Lj#ML>o`xc;VF129EMR4xeq&GcCwiqM5D+$cnv{vL6;JTJun1s z;1IaJLW0X7aSG9B4rypvOU3fsm%3}oiLQ5 z;Joq;YYy7PjAct^xdb-YI^%OJtZL@J!VcS*zs;WF7Q<%r ze*F2+Zv#1DdgUX7wN8q$2}%+2gxU)qz$;SVKFB>$Xy?EXE9n>LjOBZ&9IZz|C(lsI#?^ZLWA_QP z5o|6W`NbOj37In;tuZN(h`D)k-XW<3-MUL15a1>Vg zH^4uR^#(*>d2+0P`5?P2U*1OG5nSbcc9_;E#E~2J6l_<<@}8Z>|Ard>{SAv~g1ija zR&4!0V4J{X&u+iO=DD)#H`)93e|!O|pqr|_?k}(?##}!$!P$YYC^n%~WN8Qf*B$r< X(f`xrjzn0Y00000NkvXXu0mjfA2`#V literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_undo.png new file mode 100644 index 0000000000000000000000000000000000000000..b2bf2a8c0e0808ee35df5ce3c2a04d403bbc0215 GIT binary patch literal 735 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~ySip>6gB0F2&*5QUVDj{IaSX{| zeLMZUwyUGa@%zp$Dy~!Hxw%jEwZ@-3=5+JKA^C*d5JelW;u03KmV;?0$0VcTMF)8eGz}! zoR}Tz3k}caHC(u^ZpfP;SHpDo+su}8>34NcCTBZ!OqBmQ4H{ z`}zUn{!^{9OMM)KPhaEg>3uT$s+2(ap<~rzkzsfA}Z8FGlnMtHx%b!+ThrN>An% zIvmj0ah_GL&1*rf+I9Belgrn{TK;s~c}Z!eNn=W`%F5n{zjj|d5mBq)n&-gf^k=T4 zz}2j+Eazv*zi_j1YK*)qUy{8r9LN*%WtKTC7;!2vWZUvNi{usKdCxU$(w{SJk-8p> zViaGP=;u2-CW(ByD`01K!rmx12c>$81l{5?S_S-Q#L??UBn9io1N9`FkBAzV|i=Z(#VfSYYcv zCFAaZ2s^8of1lDU9zopr E0PqJSJOBUy literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_sticker_stroke.png new file mode 100644 index 0000000000000000000000000000000000000000..d390a1bb87dac1d3ce071c63eb5e8cf591c2ed15 GIT binary patch literal 1393 zcmV-%1&;cOP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NG+et)0RA>e5nMsHhM;OQFMU6%b zDlXB0COIfEE{H}2F({*m1i|ef8UznPy?KcsC`K`tF(-!4Gn$LHv(N6fl?9c z_V)Idu$uvff-E0xwEb8rl^$@73HFnz7#meS=lTcu9qwOIUH4u{;4lc0+mMFYY$$K2 zV0e?ZPr(#xQ*)gFw<;vzH_fsM(0J4*q?FsJTW0MF={Ok--tdj7`w-j#_rbjk{7L;G zpyk#nlxKn~z}Y=OPm`}ZjfyCEoCB2LbFi_9k5C)@4+8IiZQwHa1r%RK7>@-lz{&B@ zWO@aUtnE70dTgv`V#LpS(k0V^JRNA+IN6b8^;``}Oar>#u7cNdBSYE)oLonFIoGHg z3B*6>lHt174;6btM2#yAX&*0_C#GBv^@<6))aXf-9*!`*mHKv))w4C^pr@0SQ8ojA z2HrA_+6r7V<$9^V61d$2cUzEhmEVE8)GBew4=kT&9cul4$>Ax{|27$nFnU9OTY&r< zbG3xJ_rL+$R%hMLfIsM6ON|b%1N*@AP*37UHtRxc;M(oR!VsGv4vyCXCkhgq-ZUq0 zMuLaVi0hg(o~?tUEsc{#+twu=k7u3N=$gA{g15=DIg^(J{Bx1be_UfPv&4FWFcGW) zL-HKcKHB5>Wv{th^f`Vx&1Myq8k{-Yr!8rOave#J0sjEWsZ3(j0Owel`Qm4JfX#{* z^s;s|&nCDXcMFa4);vSFQ-E8a7t#9#*z|+<9gxUYpO>`}oGp^qNbZGrg*zH70Kt1E zaU+|MXH3suAhTJId=Ao%<6G790lJ4aP13ecidCu61FAq6>ze(k_Dv9 zt%N@V_T$CsY5qr=%IyT%34DKs(xJl9XzvFfn8w^59k1)}At&m@PB5@)XH^;yL*EL!fLjH6f9vN!-F|Qv=!KI8 zJ;%QR+75RL<;g(*$h3hpxkcsdPJnZ#6c3YTpR-#0dNk;~;Z8O!fFS00000NkvXXu0mjfOPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NHLrFwIRA>d=nQMquRTRg)+5??r zj3^bu@zF%)KyRodDzUP@#ZcIX2%<;{dJvW0CW<1cCqB2P%b3 zeb8#mEUl(|WIET$#duGCf5@lp$WC~0x zF-3WyDSSB`gro2TRLaX1IWonbn-oq{lV>8QDK8u)zg{c5URhFJ)<}`5w+oKBx;Hxg z(@1H`3q!FVx`NlBpAH9{?b`CP7mQ4iSGq!vpm!-G?bFWwQo%HJ?i1^J#XH?D#HvcA zGLZB?aQ5n?T)&VSdjd0EH5;71-|2^)URXV$aD@5*-?;Am+%{Y355Wp&|Jv!}OQqm* z;IO;jv(%;ItLjuWRD3(=0nU=uso~?ZOXU~Ct1tjt;4QeRjA~0gpHOrMMYq8&R-`>; zOrVsQ6utt6z{_Sj7nPDQW>AV$@p-bJ3v*)Tiyn&t{U^VhzMg|aVDdurq_F~0VTV;o ztKzHs4DAwU|14HM#fiNWpW=!e;=w(d^mjSC9_nb)@&x!KPldZ+9lQdQid2LDrSK-) z3#S!{HL5Sc7s1;w3|?yMJI00Xf*s^^8qKsTA=kD$AMN6r%oU>+)5=AHwZm(WB|9+A zwRq^6h347i$F+AMOWwd(?1caU&V;S0==!zQ2X{id6`vF{mI+KE&TX(Bj)RwNbY}Y; z!8(qU;VT~v{XLkM7ldmqPr%2*e=fWOUR1+mKQ2hesmDdptC3rpIWnfu1S~#rZU*Hv zdBm;-wRlxvr+L%f7vjjcC=*aFVrf+}`5q9i-nV;=391mtWr)_Lp-;wlJ>{`#2P~W2ZwUr8eGla-6gZ_Y%Lk2gD zA+i5u^+3ab90PvM4s$wUHx=S61Ct+{I;02S`K5W&YBJZS$K>@HyBvN2FPrFGnCIi| zjJpB+yQIhc^&p)9cYqhI(J#WRpa2YF>}*&7K^qd|wC^Z~a_IwH3Hl~Z3e8y?htmv5 zZ!DOq57sK$>mctLs>NxhCKZd=iA45NU0eY>n zorgK|-A_`~9LCHC#a#rK!!+;I?fsH>1wM#0(@wW%#I8|?;o3VQh}k2w37RC3&iWBL|)C<(Tc_IVfBZlQso z3CNKIGida$qVv>uvIkxEe$XU$!_Q3W0Bue1*HU~2D9#0-UHDsgl(B!()(PX|ETcXu zLG>f!F|acWYOWmOihdsm>3Q-K7kWYeTV4j$gBxwoD&*@6)(NgtV-M)HN>R}SdtjC? zfPT;ff^Q)o+;o!2zY7+_WpFl}1ydnQe#fX?SpPfw1aw3g;1(L8trKGF7oBcL$w!R2 z`fv4L_)GFO6#)7ah4i*oQ{(d>tOI>G|4;b~TBF{DpA`=$00000NkvXXu0mjfSv;{q literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors.png new file mode 100644 index 0000000000000000000000000000000000000000..c775f7d6be341353e9413b413c30ef5a09574359 GIT binary patch literal 1513 zcmVPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NHQ%OWYRA>e5nQMquRTRhX)iR?p z!7?qxam1)FDHN$Ru!m9hponk?`jR9SRv!uqdJIH`Jw8+vCM8W!U}F>!)t5d5mQk9~ zLoG7LlE$ojm6k>|{r+~=optx@^O$??%uvjNAN%!RYwdH+KIiUpZlyA8!)Kt>8K{=> zjyU)9^vs}pDx8=wk@9cY4&4b~SF6>H)Q8@f@Zm5Yo`Ub7sC6NH9L|Ts2K`8s6mEha zpsZ~tfMWIgKpI*?B)Wz(_8?4)oVnlVTMOTVmW-Cp2+&f}vN{Q7!I2Q!W;*VHPL^0t zI9R&P#E*v8AhexyJO@`mY+`k}rAf3aD1U~~-lXH$I;XM?0=B?sL8kq*AAm89#>ZDD zr5%0+Z(q_lxzV_Fegrxje)7?&zX%iRge4lp8V}Ecx7{?(D-pI*A;1*ylmCQSO2H=^o7)A;-DkPuf?s$M!2a4pn#q%yj0Xlc)a( zSO&Xb6I>i7qi+N(1x;)VTpMb9oAEi|uf*H5^)xGHh}*#1Eoq*J+P#pvZf-p?Yesu< zpwS7LUK2zr5udh*tZx^Nqu?7b>*%ZM?LoBKgs!~0S8?cG>U3jPUE(#dI>HVUQ|jv0 zU4^=a3ve^_)}+0U@=iAvt9C^?!@eyAG!aSVZaNPp1GO`^JRFu!83Y$1Uo-v>u?Wt*D8T$y#?uzOd)uU58L$lc9@C*jE zb$$$5qJjF+NsQB=8_XVxxik2v2`E>^G&=h;o#+?pqr8yz4Diop-7BTG6ZpqAhkbUr z=q>}Z+Id~fqrFfACCulvFfCSbI&7r}v9lz&66aO5p;>z!)49y?F z0UHco;WDoPf%QHx8)q#g{kS|$-wq4bNQwV`{H{;P3NhLZ>R=C9cmTB{W7In&@=Aq- zpVGLs)-iY$oj9`%RtcAoUpD?~n0_eBHkbT;tN$ksfMt6*6P}w)THlyD?EvaZgqPZb zmQr69hTNEke(3aSX|^(TQYa>yit;ZwAyqsG1LW6N4t?=3)81@SW@-fMO-*@2rg(q` z$vX>Pck@tHJAiq)DG}W(bz*PjI+PTUN3WW#psj*lIX6ORJLs@`AUh+%>CQX%wJ$qb z?;2g8t!VZ!>9dzjZ<>E=IIMADN?!$H>1AfKivWQ>PG$agf!f)x*pA>}*?O50cW)~H5Y?g?u zBjFLto|M{ZyZ|jl@}TQT{8T(##HZ;R5-$Wj^1SH=T?TU@b!jkmKbS3V`s9iRWCr>& z@t(~jD7Ep@a=Q_<5t|K@K#$EXFdMM{7m6N7g_$gXPi#j0D0KxV7fv*gLMEaQVOPRS zunY1`d#lCGoKvBXt3?trF|GeOa0#@+1khIwu@~0EQr@Z8P!8Mw<_!D;uR(Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGXGugsRA>e5nO%rgRTRhP`Y{=1 zB&L0#jw8K@42B|VJ_u=;Rs<&c(o-~OR6Z2+q=G4^_#}o31|t-hNg{&KTTmHc8cL%N z){GyNj^&u*H`Vm}!&#R#+jH+Z)7|G@lv(g&?T@wgTIZa7&fR<8rlvs|yaP4efl^K0 zDb9U;eQh*PhNlyrLjMaF;P-^nrBdl6<;DvM4~GS?4bDLx>BeYeL$fD=VXzV|!a(Jt zSji9jKLe5NQv5c+vnl>JX*&YHfu@Y6&JfU4(zJR8PC)&I#2j+KN23RfIUotnhCjf|r&OMd8K;o3NOBVROF%d4fN^e%!ARDY-(<2@SR|?qviqYIRIJf(|N(NN2h%br_rvZ z^A>2SXMUNnNN75kT%*wJov63L9Wy}dU1{iYBK!(XatR+{*L2s_ReTftMUA1pOdXAq z@B;jgkJj>eq%V(AOdFnhc^?yAfHoZ_X&3Mbo&Kp@rvAA(6sbvi0(=2q5$CkUDql&` zQ1uBgrL-TIiLIv69r&2Gp2W9k^#lRz_v5?;3oqcdb)ZMMa=A#t$EmzmZm3^DH_oKf z3gHy;)5bpyvu~tc?t*`3<@@3Sn6|Hw@Z2P6oiXjT3+SgYTnr{US!lSB%oMm{Nul>t zOp4Bl&hQ_~dT|;i#Mdc@PCQJsHXC0xAqB!>wCOT!0;tJOWTaR7lG|#a2-ru%{#yaSSfPA0y!OaiTim!{ha&_Zk`j0b%-yTPRK z|1XfqBKXNN8i3XloS6596>3K!ItY6WK7(G!60NP;VE#1#E-5G?00000NkvXXu0mjfpV2y6 literal 0 HcmV?d00001 diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-xhdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-xhdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-xhdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_change.png new file mode 100644 index 0000000000000000000000000000000000000000..2c1bd2ee7886dd44466c4715f0dae978bfd80d05 GIT binary patch literal 1489 zcmV;?1upuDP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NHJ4r-ARA>e5n9GY@MG(ekqUM1l zAm$xVP=Z203}hc%n1!>J=*r;EOcqMqsH2%MnvIgU@BzAs$zuEiRGe8FK`>?|5ud?~ zaq=<>J}{9aR?3``d|OM4Q$H#j(Wk@mkOCcObX4L%0fKwXmUF(6+hJHN!BtH6uk z56~|u#u!-DOBRin5CaV}&?s14GT>=+lVA#@Wh1k+obG_%0q&GCke1XaOY4oG|93iJ;CVm5N04zd3xAVwScTYTfySvgHA`aoHR$4Qxt$jsT}i*4@Eks6Q!@=2rba z()oC@r2W1lnknetXSQMwTX&YlHYSmM&#*tO0Sekx861OGk`?V+m4`kQ7xRi*becm7COQnW+GD6YZDL`x%O)=~z9WIkOx+1ywN0XBtly)c^{8T*V50fS$bWf+Fcj?20}~)*jwLIOwDPTaXGi?fVb0efrVg z;g=NnD`D+oDmku$Z@?t}zV)JNC;ap=e=pFBsv7G@Z~{N^&4^&TfzzR85f*?ovmf^i z;P)(mY1N+s6V}z@@sNZro%E>xAH-yJxf@?DUBuRUu@^*^MH2Bz=+a5|HraDxK_s9_ zFi|b1_)ef|9XPuB$X<`kRU)O^Xl^hjs*BeBAZ@X3K82tySFI{rq1%1tG~47U?B{LS7*V&L^aMVbmguVN7!(VG^w5!-kPRYhmIT2ez`3)l#BL7;Xe r$k7=(A7dGPnKN4KTl@#+=pXnSG&s3TBn9a~00000NkvXXu0mjfgu$~> literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_set.png new file mode 100644 index 0000000000000000000000000000000000000000..9a4a5d71babc4952e1f698cda166ae412a07786b GIT binary patch literal 1623 zcmV-d2B`UoP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NH!AV3xRA>e5nN4UNRTRgQSo=X~ zMeJAFqF@jgrL+ZIi<>UYT8axn+>|z5C@q4T+LUNE+E&oI&`oWmQE+L+WK(Da#Z(Za z3%|g|kbYZel~%D$fB%=c@11vM=FYr%iC^@<|J`%WJ?GqeXU^PvW?o0f9lCP`+PVUr zZFw8#nVFeYh`nF~=mu*O&~!{EI7@pPeA3z3d6D*?B_`bs_JGg9O;DC(I}YTl#s0m- zpv%Fl;CIk2DaIgJUS$<6rw{}6G0*^5kul&IbYox=gtU=aNT>VZw}Jo!8AkF2dx2tE znm|~W;nKQFfxwiF4*wZg*?P2W4`QtXqrlQH2<~nz*Rti+XiE-a_WADfdlevxJtUdWB5Vp!u_+GZS zn|Xn(9{<(I+AbeX^xx5r;(sBLqYeH_(NBS5h_uD_;D4``z_#CP?j!ZxTQqgS4=?7X-$!j7NGhh zkPfNnK2QHs;IH6d+FS6~!3`kZlYF+tCPcr^347S>j@j4xa8O|uXkW|$BVBo4#9c)9 z99S59#V0!TS<)h+cY^-?#^Gd$nb~5fyt5OEmIv7Sv^kO)*eLNi3M^eV-6fs*&9fuaV8N-`@FrCuVos>l|!a`H8J%@mq#kk12w$> z#TKB~zdQ;DjQVFll^XtV;;R@U8*^6E_?>RBO&7VtFTk$OIvM{O8%|gWe{e$n=?#kH z#K)fOk3@XzTx^!477&RsFJ1NmHciZpcEiYv44+y+?nc05?p4x}v_8v0eI z_)1hK?DL@hV8bs4yTK)3NxrIB1APJWU}J;^hyDQgs-el@FtX*eO4*`vdK)%=5vXb< zv`Xn%IsGL4Lozm`JF&n|51lGnn@ZkfR>sJ`&=kHw;iEg@(+O2B$+lMM(k=kUjpgw$ zGjyB44scJRJyuJl}BsJ|)5MC*dd7mI_ z4^I(}da3^rgn~``{u6AU_UKRf1qJ?Euy!$(9Jjy^U<`k|^`dGf{PZ&4jolP{54`3e zI)(1hS+?Xa0d@jQhf2E6i5Ua;n87D11tq|U2_kk^r9c&&7;8=zpihevnz6wvpa z0|EmorFy{zuomb8f!bxjlTv8NEB{w=**nnnFJ86oZrA`+Oa1qVyRZ>#2f6>^-v;2c VQnSaS22lV2002ovPDHLkV1mM3?qUD{ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_extend_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_extend_location.png new file mode 100644 index 0000000000000000000000000000000000000000..ed72b0b95b4825b2e2e3477870efb99ef854bde8 GIT binary patch literal 1657 zcmV-<28Q{GP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS=<4Ht8RCodHn_Y|^Qy9m08XkH2M0_Peh-gx=($H=~+Tel^ zF4`)sB6O*?*82U|JCn1sXFkryJMYY!_euVH=6pQQ^M9T>b7tnuyF)_*8DwCPfk6fa z8E9+;N0U1$~tz0=fn42C?KQhBko(txgmHTnENMx8w+hp9812Dp3&D<)lkNmqi`&4Nfj? zMUo&o0^X`4D;Xb$so&Y?Bth^z@KuI*-PMhaOcGg`2X@t+jU0dXH7ZGvoCDs@A=``Q z<2b#cF-d~VXfLu*;`2B9mxd-O_(>WP*FxgsP$FH@-^tVWH6ga=geZ4(M?>N7w|XkS z?5UTiIrH{S(4xenNBJqUVbViSD&wAdiJCKS=LB&b>o)APekANV<-ttdr5d6uKO-*A zG}bvm=;*Udh@26i9HJ|?wIt~8fB>a>S%ALtBAfAbBvUV~I?o{1k3X^cSE=Rv0gJgz zSLb&Z_Jr;^J71#C3F^?-m(LJ+(p8zHYWCdWs+Sq>%-c6X`YaqGHxlsrssAqm=!w|&kYd!yie zGQAVT8JQwhJ)87W^piYo$X^Nco~2TC^QU_MQhyE9FD%r{W88l|ZH%FJjxB1n1NBQj zu#Ks$4FcPzY1I4YXWUtnlLW4QpmDb*Z9OR=5V}{431>-PQ_x%lwgLTsN@cn!#_>Af z^{f{ynIZtb1a-=)BmkT$DW+^Q`p!&_eak4>h21&`yyQ#5LvJoOiRmw}_&$oh`I>T! zKJ9u&kyr`R6Zv-_o!(K{@c%G+vi&MzRjDCAf#VTY%tsU8f?$|BbRU<6+XKUrQTA-Yp6UQ< zSpg<&0p+x5CanjnfcdsQgQ87$#(*|e2xcvqv<2nRw%d%^rf2rI?wEicvISMKZ9n7m ztv(f-UfS8#1A=Y literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_location_forever.png new file mode 100644 index 0000000000000000000000000000000000000000..15d8905cc08de6a120a0ad3a99babcb5e37e96c0 GIT binary patch literal 1255 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(<^v49!D1}U6i==Pq0fhEw>#WAFU z@$Jmr*&=}=$L=06xp>MgphqoB@qQ0WPZ}Sa=WU7aGnnlop1J}=!rcjx-p z4F`@$7_jv)CLbV7J+Mzum|P~m>1K|x;rE8A36d+Al^;k-oJuj89OEriq@#Y|nar#m zevOx29OYif>u+_2i>mVa~pQMCi_m2W&f6*$do z5|?FWM~#sCR;7#ImrZPtus>*~>mFI6GWopLtFw}apD{`>T~_e1yR6V$*|=c0#IpyN zyWiJ-5b$A|zGwNyjS8NYavqxmT6!(_XS`;9{dZ^OI%f999!|%XA8((sWwUi$d|-1= zeC~o{pP$CDeGF5`O*DFNbNXAaw3%y7el~q_2uaF0$B^$cv2pvg_lG~LDa>zCn;+nI z&hJJE^Grk2oA1s~|79z=b-Vk$Ie!Z$C*Edz@;T${?+<$TTi}l)PndEcGnf3Z(G#A_SDh%RTg_f zOIB%VI^L?d?4Wp*@6z6ot4l(@vE7}+x+F<_>7?Z8O{HPy9ACSKta(w^;ZZ!x-qXf6 zMeX*>^=;3kHe6iaUEJ@Vy1Y`eYsp~+4Nvi|;~WBJOXE4q1~ly{awUz{f}z6v^u%h4ye_t3ZQt2dBCds=eby;56V^6)KRJ8j z?fU|~^Q_Z_bBm4`a;$p3+dT$!xq{I7C;)Rd&u! zD|5fcVfypRmd2i&n9`sZ_M~IUC--%6=^lFXqi@W3^6Cn&)bxtNnD95(nyS|&DCT~u zJZ`5{cr_qM+V#W%-OaPNu{g|~F8MC6@y6w?`wjkB9Z-HCG*dD7_igv+N58YZYWxci z+ViDzezI!cog=^Ht=A%(Clju2mx(+ve==_Zo5!73e;!XbPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS?HER0**jx4FxMfR`xrEW`OpNmif>$yxJJSHn@|E=}6un zungp7J1BfNXjzQD)HyVI*D;cv@WVn2602{behT^)mcu@yNzYJyMaR)Zja>F8j#0ki z#Owo}aTUpt-%9NZeELfA(?DO>B-1zIDpwPHt-vQq1z4sZ@R`lgj)y6IM4L+z>HH;-!F96O>^Wz;y! z)5qu5^;nxyb)?Rx=|J#{N8OM3`=>4*OQ6OgPamIqaIB(HPrR62HBP!; zyg&X0s2>zbEoO60F-eh}ZjtSv&5|cbU6`a5d}#3NwePTf;I+Ox!{HC1mxTl+#2l31 zGhL}ChyiMi)+JtzNm>PW0{AlSi|jXLTc_^xBV3xzO=*ISSpAVwS?UR*x|%FzkcY=R zF-dFTG)b%DzR14TY+Acr7U4oS%?r@bWa7#)K|5)r=U8tr$fM%on56IEP6R9CzQ}%k zwr7)nZG;Qi>>U!65VIq}mz|4&Rh`;(_8MqahHnX$0H57#R^*6xFl z=A&?Uoftl{l2US}MoV`|9HJgDglTPdiB%ZB0hnXt#Hq&=>!@)lKHvH;UN63XuvI&A zj;WYD`))EJh^he z44PS^fj=E=2Wf4tRWCOVb>Dat-r;Ia-ff;-xpl2&-U@*~5%|`BgzRP4x%A}1)B54P z+S@z2m+d<6UXM>d$s}8W(_DeW9}Uvn0_mE|M7W9~ZV(7DJr&V~VKsxl0{BkdtB5gQ zbAj&()&rj{uhu+o0!4b-@vTo;!LR3Qt^@Cd`2O(JS%bf`H758&fNsns*#s*$cMe5& zC8>(}w363iwVJ`}X4sBce0+BuM2~985bzzq>Uct7U*AwIjmmE{?&A>UqV>#wUrQs`L9~>W#bT}MQa*cPOy1D8vYpYlc$&-8y#;A5Pm=KW-NcW z6%UX1LBcl&3kvxoNT0>Fm_L1{j|Ah?qy z3cf4&+EYxAvd?kkH^KKDxZLuWokPeNP>ks;c$g&^{ve>|>Pe=TB1Sv%wf-~Lbyj?? zoP+@1Uz`xrHo_ih34}iYd|+nnA$74i&dRSS4w0kxXimMgg^c5@0l~KdZv|AGXysQ7 z#{hIJil0FO#`RywHns*^1A=b>76G44wel;5Lw$eXTVEv&QU~6l)_~x3;C((Rx!}8x z&ze1RSp%rz5cfzyXt5tU@Q$pi7yX292tw{l&nC`X|3&N7$Tq^-fnPx>rsctv)&Ssj z<84+z@h6FCXw|534q@X01`rZ*gEbfub-bG%P~Zh(%=MpDx2zn(<_8QQBxH(9ILT83 z3cN;4>Ia6do|*B8(&Ev#WC$4F?vPU7$JS+nUZAKfLsT*AG}olf#9=-vhaU@c+)6TC zaO%GrE6WfyBT02i-{Zua2VVG#fzE(Qrlm{jH#~BkQ3N#wuKz?1KknK$`(?{{GVF*AwXBv8G2n z9YRM#YTOPeD)UFC-XQ2-3!v1eiHrCiXo>nSmSACzI2hcSElg@p5_r9b?XVL z`7|R$6uCM{d>kzp+cwvIA+>XjL1f5MK|g_Br3#@&8}JT@+ja=^-gv1!Gs#EXt#QSX zeI0YUXVQow)Y=z36{)W?UB3TtmxXvlPK=1I+SCPI*DUJCYf!ff(4|20xUXXO5jzs- w@v-hD%>$LSB&gV#s})u|1GO{of1ZJV0WDz&WOoaILI3~&07*qoM6N<$g5+5HGynhq literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/large_log_actions.png new file mode 100644 index 0000000000000000000000000000000000000000..609d815f0f2340a6ac23601c0180220fc8cc80aa GIT binary patch literal 3491 zcmcgvXHb(}7Jd@~5+D$IuhNmG(j^24O{xe;HzK`-BE1D$0QqQAK1CoXB1JF(1VRKt z5fGFjAib#+rAiZ}ZJeFio&CA9Gdpw7dCtA(+_^uV^PHKRY-M2tW8h-|003rUjIyR8 z<&V+RQN8uF{~0QPLamMTfa-pMZ`2LS!`{Tx+#Hal#`FLP=L10glu(V2Y5+ik2LUux z1pPU~ga4JK;A#FH|0y)r(&(i=3Nu0J+C+lZ3;bR>+j4f7zaF%vozknSt240XudFjk zmZTFd&M}J1zHEcCK0sgOgZRGO&Om}Vh1))UL?1o17Tz<>Da*W;GKwF{hASn3mhNW)p!9DMDWylUE0n?4aF^;Q_Nk|O{{ee#pZBKe;v#~8PE*s`(}9s(c@DCuS@T5zOv$~)5S(M1ni zI|zN}*-ZI6DZ9+;vmS9?w5Gke23X(;c6vtC_)K#j8%EE;#=~3{Lf-^0zmlG4 z1Wkss2fScA@+>{(`DE2&ylbBgXoJ73C8*l=uMj7dn6KXtl)FE4#U##~e&miCREhj~ z+soa8Wwe5MraP_MNz026>oJ+~Hwxn38pY52_)#Gh9P@a0k7JkHb>~0-U=zOAan~xfR#H5m3}r6)Iv*jpF;_iPeJ$M6Uq>E zr$FKw4yk^m^7n;iiEe_wn{+UCFwwI1pmCq#Ygx3hymD1zN@vDg-v4oXuv6x}83COx z<;wB;nACN1OmrdL=|q;7JtFO|Q{SeCy7hUsU^q|drda2FM#)W-AVfdcs8 zq=LN!+0j|--W4s{9b588k{%noOjUYGvrBm;f40l_5hK-;0xXT`F356Ue9a zCXyg*u(DOPKSyoCO(`{e`)9gIV`4J9)ptG2+pIDBE z`)ORz^k^iCLEDScy*~TgrUj%5JnfusP=7OdGIH*Cq-tW(s&Zm20>kf{9#BA%0=!5p z_~9DW=F5)SEc|&tec@qtR?E+tKlN=zjtO^cK(QSPy@Ni@W&R!Sh2evyO;w%5@cizd z8RGZLX1=@ZG!FZI@+*1l2cBOUyYZIHM-*Q-biEg?iW#&uUbK;1t93&7kB4fxg^6X8 z3JseIZv@r5{Bl@^Qi?ZQhnGFw8Mo~#6JjJOEuw3#@#I<+Ya;)ODt4 zHD<-GvSWmP{MgzuT6$3v(mqcTGOQfWA|4>Y6)|9^ifk( zIa!0w&gTO50_)v{`42~fRX_uftu^xFr2V^McoC+>K;9_}By`XMwOULs4bmeyb=9+5 zf$P|ZqNTx?u~r+o#C1qEu#Tz|O2M*;WRpGowLlU`E!HZW7#>3ZAJ>_DWq&w}q~TXo zJB2KM$z_d>%&s^!j1PP6!_%~*e{ps0k>I~0875US&bYq0A1ydKrQ3-~QZ%2m&=D8X86c^&ZY*EsIAF$gkOM~M z>f`nlppD4KFAPI3Kaeyu#VUrD#+(?e?k$Lb3BQE-t986@F34rFp>mD))Jj8gZ%0sO5D?wM;lKdaSIh}W{BJ1 z>k+o?#XCt*G&}Kx9{0+i-Fdw%MgAssy640^i3qiw?&?4$u$MGr4C46&*IGNA;4uzw zUB&gHR1Ev|)@GRGGM=#x)L;`R$M5tLSD^E4&T%bIuufo<0JvG8wf?RImA2Jr-asm= zDR%~`zIaCQOAe5d_}|B31Iz(w4UYyl4A;WF^BJW+@2;2BHR+G3WQVE8 z9*dxtrX|fj6`yj4))%L346)6NinutPvB}W%BMdJNp%hz&*eIn&EEjfyU+IpzJ^MBk zL!0;R$G$7J$m?n4i^n?8cH#;dm})nT=Kxjh-xoUW=HI-oRP*Tk+CP~tWLg;VOl9hj zwFaB{Nvi7AvE8>Vf&AT(5bdugox==4-{K&rZw47(Ayer*CZEO`L}8S=-V}LuO!KkI zfX+E9EHiO`SgIZ_dAqb-Eyodru0yLsi{grbR#@*{IiK+*f7sQh5?GCWzW!T9OkWlh zVE5j=P`_oKhvN>l?}QMbiLJ>U7+p`UFYg}T=b>>wJBl%!mNcy{kDnVA(_slh>>^Tk zHr;uDMPV-x=4OkyYETwH=mE+-%GBRQf+sOaACFeZB^6Lbt2s2(@);@(N{Jvct)Zx5 zPEOnBv_wL!-aPO?OHoy9ajWiCBo#lqoTJfVwF2LI`Yi4(RplI;ZoK2kST;Pn;JREP z6(hO(C>GR~C|L2n{)38d$@X;NV({a@!Db3E8NU|3(hYaAEKW5_{+6U&@EYupTE>LM zPSL=pahU$NAV4*2sze(IQDN7W&^g2WvL7`D>q(yB%bN&h+`7~Eq=XfRRD=u2f#Pp4 zw_y@f3ma-92bqsnw!NhYBP**!#7i1pGr{T8u$1~P4zht z?!}6PlxQPU>?%|&M&GQS_BbJNo5kG^>6T)28Hf>`4M_g+si+7oD?<@@hdc--P5r=YneD zVAAij_>ad*Igq4PHhIwd>y^+FxsXr+%>e_iL!GYO>06c#b5vcQ9I%1*uDZwf_AAc} z24C8SA_Dcf##M8c=)WR_HgI>F8CRPjV;F~0YTud`ogw^u{9&crYP3oct^rC-iKA(0 zmZ-00OGS=|S}CdZP0Lb=l|4TxbelS!@8)~Bb5h4MCvO0YE)oiF|8Tx01?vUAWyWFH`fi9AD@y4%|MpfwEuv0eLt|XgNROqq+;vGfWRTp;3p%G!Pm4AccFA9#;8Vd+JWtp!#UF+(KjU zrDY%Dsv4Ge7EI`3zx_L0l+dMh@WJ;d276^UmfipBPVZ2d`~yis=6tINE#uY8*kpio zMni*E>EjJFWaIf_LQnHX50s`b#f{{dDl B2A2Q; literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/left_status_profile.png new file mode 100644 index 0000000000000000000000000000000000000000..869d4874b1b001b6097f6792af2a9827148991b0 GIT binary patch literal 2573 zcmV+o3i9=dP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS^cS%G+RCodHoLz`jRTRfZDV4}C zq?ic_A!O171s}vvFog)VN-7D0@?A<9ODo8idWl4(%n-&NM$L*sks?ho zvq1bp@~aOOar*sl=iIq>pS91~=i|pm>jgxu7$`BOE7!@ew$*U5jvq<4JHl!Xb`FMvWRZz;Q^V#CCYVd)j61a1eyf)XJph*y>5pg5yb+EnI_74QcDveKnF;hq0Ugh zyroH`kSjJ&4n9%t9VryWt3(Wb^+iU%8)#8DtfCyETsWAbHdNb55bCx{yK>f3KVsG& z$^|GVpQtU>+-?wQK=zF}*Qr}Etd~qmaODP+qa|un`GFe}-)wb(y7?*jjfg7c2$ZWO zn@c4Lqt-c==vNu>of9`+xdPvnl)6sxuB0K<3i&5s4ZP2@Lj5RCpv;jt;$H|9@1cn6 z3`ebizpCnKoj4i_J_N34H(*xo6*q+2fhFtR2zkqp>S@0R>;X4{PgExx*?ND>(D-op z25vo;gbPG^@U%ozd8ye7e?4v-vdA-Z^3j!6Sn${ErZ!j-_JE70NRAl{T7X%%TX4eo zuLida?ogF{R|f|)4Dr`G$y!XR&DlRbM!K9WS#HD&RzbMIA}y%f5FFSrB&Jr}mh>3r zgDN~UHdqTnZE+SBI9FNOH0XZe`~$Eyg3hH&lU0Qi!V%(rgIsO*k9AaP>(Y|K51x?C z0UB&A`39wzTXjG-mWXq9(N4lw+?I5CIkDbqc;nOxaqr~-!8?bVww3{=3UTjLyXC3NpP z5ecGYE*WLT$h=h(WRU`2ZQr`me4A0L*~{w5!V5F_rn^xo{|UzVlFib~H{#&XB-68e zef6+t;p&R|qBfhwJ+Ifn?i)|NefZ8t9H5V%s~SxY^2~F+QIY37@;zwySg{N8Yl zt&O6-P@lBL9i&$(t{fnto31iPxx=tMYv}T-EDkGH5O37RuMOi`pTr&1X&C6eRT;6a zl)|@HLn0Q36|2D|^VGU3YkiW|LB}&`(+#v`;mR~uQJ`#bSh4a@TWxLXAbo=3isj_m zq?La+DrYnJ6}}xJUu*Sj#WKQsRaRSTeG*?m$%Ro{n_dSO7VhoyI3IQhG&8Jnba{&M zt<5eCPKTpd4XWIyR$FU*5_iyegYuf8%d6UHIIQ7Hm}clxRgupc!{{?Zmse%Ab+Ate zegn8t_#Jwj9fVVX_4x7wdh4o>NCEjo{M zs`G7?h%@*q^rTl)!!rfAagfqBCZlN30JGFwLXbE$XX~_P6_5b3L16-`#IoMkajh>w6c}Y zoQT7%FI%?SI@l-Ne=Cf8u&->?G=Ji0@K)SUfi*r!r@9qjVj5T3I{2+^VZDj{PcWDT zT=@${B~yJIC+$eA37|8=gf!bK>(oY|wz@K_9*3IBH_YnfBm9K6XK$EsUk}g@4Wh0* z<0}4#Wvh+-QJ)Mpm!7PA(|(YBWS-IH%uV~o)vE?VJ=KnLn)5Wh`Gun^TqG%tFK&!b zzFQbxO8mN^-i{r)bfenksIOCQCq{B@h=cWJW1mA1T!e2jcn)j>CxA5=qRu6HZu|}G z0WX4wgA;NL@eO}*C|?}9fF<77!%oav5rPN6JK&~8)&kv5IA>V7_;lDW@Z{0u^HB$B zHY@e<0{;3?;VKwvxkbQ@Am~LWcKyJW^p6+Rb9fZ``~^P^c<;IqhoRh0%+#F->X&=+ z>T$20`XC)w;HbwBJzToW@3ZJ;n1dG;_U zDGk}yXcu%2$y9LJAd{;8AjkQ)hK)Mxg`hwc7!gY|l9lTp=xaX^#}&X5`4!vO#&M~| zi0(R=50-f9->9J7xhTj(!-8fqSF|UtT$QsWOLGNsjbTjtQ-ppa;`ivX22nRmC1v7n zGV;-v8m;+L1Z55RSg_v+>{C5iNoxy`kdPLr)@vp!SG8$ufiOuIh$aDR0qF)lhoWib zNV2t7L;TO(q>QrK67=U#L5*Q;aG7Rl8a$QJy!}DzhzydF)dw>C)rQ4Un=(vuR@3Vp zAni)h>zd^`X)7~VY@nITC(7MjAXXN?MnnMJZdqeeKQ_4@aLZ(=SU@q;L^%iDR%LRD zJ4plg$7$I_b$dB>gP;e4;A1F1go(*vTQolHGg3KD&KBD90f2y;2=wheur z+kx#%492H94!_V*TFD**!!61|Gw#R}5*rPAK-x@4bxTAs6+39@GOWEvlG>Tn_U%>> zy0XPIw}@LY6sz=bVRc$dNE-u@xHhOXKIyVw1oV-18M%P-UeE_x{x7;(-a#~?F43=i jNBxtxdh&Nq>>l_RaVD0c&+UXJ00000NkvXXu0mjfpV+AJ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_erase.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_erase.png new file mode 100644 index 0000000000000000000000000000000000000000..40b40c9c6d7b52d1aba6db35d311762597761343 GIT binary patch literal 891 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(<^v49!D1}U6i==Pq0f$6EIi(^Oy zc~i4+&k6Pt}!8f@;RrVj;5;15jTIcuE{wf@p!Q?H!JtXjY2-D zD><5yG(R$PbanK{{CBtAVEN|U+_QG?-$+`Vd3Wy3n>qLA#=cXIjQH?~N$&wVVirEZ zW;WmJ@=U+w-E#_>EFAWn+w>-NDPz!Eo-=hxy*HFTJ+-uU4?b(HrO&{U-mIZL+eD^Y zN@uH|iXFH6#bfOv2R3fM`C|f;#s1L6OZ@6puO0~8TryGWfT#FM$2ngnL>=&CU+F62 z`s>KCntlGS7~Ch`+q_Z#S?!~BGyGz|2+FMc++&fsZu`-?%b%y5F9<(V%2hslU%^Ay zG}$*2?#nkXkzTl~e8IeeBTouA+-_H~z7ll*RKJ>I;V$z94CnOK?tI&`EGF5O<#P7y z2LjS9y7MhJxa`@;%lkh5y{JM-p%Cvwnd!wZi#sy7U+N|Ef1Z6sLgr{L=gT-D3tdIt zx~F>{T;1$C&$2#W+jXPqTi-i*nU6HWe3xt~%u>3`Sbl;3iR|65uB6vp+LP zelpEp1lKGon%(?(=UNffc;MH8Q1j-#CmqQ=H0`~Ng(wrp*1~r! zGwNl0C#A>M=D4Cl_?Fl4*U-(h=1S^LPo zHEmNPg{Ry7{~eU8{kebf$;sF99{t<)<=@*A@)2=reN&F8_KDvOd->qW1fxk)=ZC(U z7Ak9eQfls1DW}ZGFSPkCY?W2Gd*QQtAoCWVJ<3lkL&BE4WiBjRp|Q69q|2vI^DWrD s8TNgWw~F_=^=AY3js{e8z=QQ4gSw>2RgFVdQ&MBb@0RDr3_W%F@ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_restore.png new file mode 100644 index 0000000000000000000000000000000000000000..868f20231b27ee7b4b501941ce94db511ca99675 GIT binary patch literal 1489 zcmZWpc{tPw82*hJX2wx6a$9mFa+7l%WgLSU#!+%k7)MbC>s)7!^dLu$P030`8dnk` zV;Q-br9p&D&K=`EYGlVhyZb!*ywCf+@Atj$-(Q+7#+-*!gcAS&9+U;rj-?hSgmJK@ zBfY_#C7=*H^D6*xNNk0*An{HpA2b?JV0jn-O7#aIClwY&SOfrY2?zkQ6m)VcVf!bw zC;|WLPl{P;W()ve*GC~QJ4Ar!k8EBznu_%>2K$iK3jD|MN#|1Dj&?Xh4BW;PDg|!L zmzEeoD&Ja6%h&|WOR>pQmP$?e&tbhG%B}|rs=Tk&osp*axl*L!mdg0{cJ$|v-?WQE z7>sb=#i-1o)9nnV&*J`Zv4)24(5*)Gubj01LGv9O0)f~jL2;Nr>`@5A){-34r)S8$LyT`2H%TMp%f$8#C%7q5a=NN4*fo4?=yhkk$=+UM<2sv&fQ&- z40z{!Rk(s7eGo>^p>iNM)R$m%>MDQm@;jZ%$>U+JWXuAQcK$(8mcK+26ESCmbr@+f zQQ`�ySMh_n+t*hf!7?xhBWw*hVOmLUmOEyxG?E?3KB8!q;H)5$p#qVaAaL<*GAh z;cnl|TJoJ=rHUEqTB)s*dO<<0qmxBuhoo+J@WA0XnWM@3&#tAPHyRdP`rEy>`6bav zt`1>2^?5-^p+n^tFRcUe=1Y9|xx%oto`eD2daD`m^p}yxGAp@i*=dGyH@3A@PgQGH zRmI-pJrmeymdq^YeM(e*Q=af3Lyh@>$wAG`dp}tc^jXs7-q3|Y7hs0H6=bvj!dMq^6mczJl2+v2_h=P8}| zql)+eY3FYU(szzfL5~caccX%zoAqg-7$H}M^ovBftY&Q=Zqgf=#bQ}vsnVK|D?1ZG z?zEZQh3c(EBCT*P#v^vCKkO!)IceBYiW+1bdXrc~-jr$KWtP9<4)y@nTAdbFDLjSV zPr>!bTgw_rp6d-Q1Xuf%vMF4YBX9Z)PiDOPj^W*W^zFRXsGZz&>y|qS5+qZ}P!Tb< zq7FrEyD1IQWm_{(Il5JasI_G=avdU(k6+n6x*Xjm%0<_YHr#&|iwIdj9 ze}0LT3;jN$p&0s9rMQiHL&yFTT6ICeOp>i3XEEWs$Z+n++Q%xLt@``FXvb_chff*}atAK|l5{OSy>dj3}ysY|o(xfmqQs zM#`=n%x9&k6J@Gf&+XkMy(rsL{6Tu+%yr#@u;r^JqMhTxI&r{<MSY;>$a&G2qP%6i(^Oy z(kLt1w8zx9x;#}mUHG4{?D2w&%D~&8i>|MRJ1)DNm zxE=olW*m`UDKe#F&irzjhec=J?JUnvFVEZ0zi;QAGw-VN?aZyMjd!n|=ELIRfCV+N z?7I8TW>-TWJAX!zV!*qF%qic*bWLU+pSX=V`S1#!n~Rm%O}}ynI2H6|G%0(So8GDoK36$2|du<)%`5Xv-8Nj#a1`W zC++CHbG>qI)Fl0RS8SH&ERI!}t65j|O>#0*)r7aZCe8ZnvNdk+6H(ixj<<@o&MT7A zU9{))OYyJXJdbwQgysK9itG+r_2;?6k2%iUFK|yum0xKQYCE@%O+{FAQmbkj``X3# zHB$Vum{-g%DDn8aWBP*4@=7i@O&yyU6v8gdXIK(G#kb1%Q>u^C;;JCc+p?C0(`%z& zJkV8-Ty^TE!QuBjzmgc+a!xPw{HNz(v|4@Ywx?ca&MI1b`#QJ&^&Fc?F&sgev%ekL zo#Vn}_V|iQy}63?+l~Ai)0hj^yqHseTE=!#!WQ=SBfk<|+TNV9IBRKk&hzn{!&~lu zEAsJ--2053@5KvKvsR8?^KBQyZY<*yV98OG-n2L1;fhU}EG5bpUVM*vWY7Hctk$DX zUfGKzem`dn$T*j3zWM2momcea1i}KOy06~&!Z7(;CCzg24;;zDO^(hJkB#K5??4>B&*YZQX7Ddeu-|3*2w oWZB1G-u)f_IvO~zq9ra5zopr01*Ox+W-In literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_sticker_stroke.png new file mode 100644 index 0000000000000000000000000000000000000000..159f44b9c9f63e78fc362db653ba8ef12cc276ed GIT binary patch literal 1913 zcmV-<2Zs2GP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS><4Ht8RCodHn_X-bMHI(-1t}O2 z5cyD3q-t6Ti3W*05NS(6;|B=(q8LSuU}8dI;)96~CO~5RB2iy>G$9yNVnU2T9%)I^6%X_bIyOxoI5i+JKbAXS4fe8 zA_GMRiVWm710~;)_4V~#2xl8;0HcAc{D|R>QmJ&-<^cD2>TU&-4VzPxyTCEf4aYg7 zJ|9IoFdFO!S>+=fCBZR4KN%c$AU=yt2Uraz#)yVeK|squrLsip1Ef!8AU=c7n_#-e z>7u*9#VCbMnkkinHnV9xp7(;cGc)*fygyr*T=NpQYRLm9BrR=xR&FkZA-x=Fp+M z6SyQdw+SQuQNVc(RyzX07GTPEC?=^6!$e8^FM!kFSFkcu*f=(T^T3q0OoTacqBD0I z9r}mzOj~$K)8rnU%ptg)+vPqR*)Y*J8*$2`%`!tbc#*7rXk=Q7iwF12w*`G@m5vy) zJ5|&;%dP#KLGlabygf>!>X#TxAHYeYZ!*m;(#UL6>?(}Sx(=pSnw_!M-jM5pKI}09 zk!dEo@R*oM2n`y;i^ykZ{j}aDnYVKJ`*A7 z;X2(y7IDtu<)2DS7b`k_1Tjy$FqVTWnX7xjQgny;tU0mXl}Lyr$6U;6ETGUFK1p>kK5jrKP|6|T#sKpJUCh?1ATeu!JfjHKS`94~_~dp3SwePK)46%T zl$+cc1|AA?xdx@_hi!^ouaKnrw+Ta59&FbsJnMowrOK}I&1Y}Pp@yO3?KTM4$lC|` zOpwF(k!us%6w7tczJg;Q%n~H=)ntN5N(sC{V!js0wdk}&)ntN5L_4@Ik`TETT})~< zL088zQCFww^z$Iad8Dbd>7?nZmmuc!La+^N0*$^i4Cfu76Py4~`Q{J#Qa@FPj!B;c zd@c3wgYY@-7IX{P>~$vjxz@q82-|I7OyDE`N^#F$e!>azeUm!V90Dwgmm5G@|Jgvwqb<{+>4~Wt!~`I%rh674cn)6@FibCq>j8W2}z&$Iw#1sNGI{9uH*JA zcb(Z_OKRtG2U++xfE(fbw7e=+NnTbk#rhi&)3B;#zP&l%74S1~75Tr~Ghl{~;NW>s zY4~=HTisr3hQ4(KD4W#VKpT(~OxYt%05VGCwtW*zBHZA&{}g7C0k zp6ch)M)ZAze(pgN1lc?+<(u0B!O4EF5%7n8O{E+61DRTz>D%wAy9G(~4kS}TUaTra zGC(rM1M@Y!cZ=)<86Y{AC<#K_VI_x1&oh(;j4+A~F-%&T%# z;w|_H5wVuQ1K=gFI8s&lC4?^mP2{m4U%v@ex=W0czz0SLK4lu`$74_E0TgT&z-8$Oi5pe6q{6N)T5o28{vaE~~x99CG}?MJv2s zj(;pKf`}BTdkC0&HB?qPK+W_Bh5t($7z>^U z=G{%+BbuhQh~8WzQ8~*IjZ<_mbUL#1V7CEiPw_VT%JeiQTY$HK99*3O58D{2t5$-v z1(@arM1Jq~I*{o%G(zJtq7u)QsIS%(TM2hBh>Dc=fhT}%y>w1i$=R|(LxQc=B7Gg9 z$?4*8a1?a00LP9k&=*oPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS@DoI2^RCodHnt6y-RUF4>G`FlI zkrorz)XWx0B?>K-q)j2o%F6yRNFs?cA_~MQ{6{1+DbmOUNzoRHEOJNGC@Y~9!=+qu zBTz9-bDuun@t)zlRbRsu|Qyv)LkHv+4inz2ijqn@Deu>v>MKd7_}64Z+NZu1~0w^U998GAy&Upc{x zE!Z5wPxrLBCS%tsLp_0OuCZyo>lqKVd333t+b(OqS=I(z{Y0$S=sHKf)ZxV*@yJei zWSNR`Pf&Gr^(jyA13XdobY!*ge>$?p$uf$TyYCLX4ynVy9bgP_m-^j}GaH_$2;Mip zATCNXJgOR}h%{7#Z;Pg*@Zka2s~cxFLZTwz_F!dU9=zOPq$5MrG;T40HwQ0+?Z71+ zLlyvc#mhA*)wx;=F-8)!n%)Syf!5#v_>C3sU&;oh+?RP@v?Ssj^0VL=_y_2RyB1s` zM$dy_8}O0j4>s8>5&RTiRy?vPO)g0q8J=7c~(`KOECXaeUE%TRof;;NSTwafT{hV&;vY8}^U%msl z9pn}ewlet&n_7Z!uoHL%tl>BO8~h43!DqVRLw|pudmoEZc@19H$u zlUz?}q>0$2!FD?ymTaT;wENjr1h3CTUxGol&Ls83BM9TY!6J;V2BSdO>y+3=#DIJw zR5l+0tMPFexGAEp3z{Wz9)lCmv=I!yKx3gmLw{zWD0S}r5*qL0`38J`17v$R$3RP< z*Qprka%&D43F^Lcxd9+A`T9g@WAp}XKc+kgiqRK5)NMifgyLqPSaLK$J_)=@u|1+q zstGc>(c1z%4%UJ&(%h8(iigrkAr^JnRj|o34u_Sr&m=*%J#0J#wgMkbw%e9n$3idQ z`zI&;%iNW54bUg^1j#4tv<3QF;*$R5rgs#-qfXKI0kZgZ8E;LEx&L-(s5 z{kM2rizh;TLYx?JQWzD7oiJZk3)Gc-L4gQEujW4M=k`;t~z%-y6#fBo; zmJfa0$dS!-oGN=C=h{#b`Z`9$*4Pcyan_to&s5sbjyZp$!6$nCeIcDo4&UF z4y#8wtk(DCz14TFJqSA03#+Ogpk8Bm+MJ@kDu9xz`Q%QZRjn8389;MERQuW&Y3|Z_ zOxOxGgLT+5^A>FS6xBi7@)DS5Ex`bi&>lxMfnPvD04sSQ)DwNQKqz@;A~vPkn2Fnz z$Iw%&2YFMH1TDr%J3-Chhk=E0oDTvv35e4**R~2SE-k0SS*O$e4&P|l*dvHvURNFK z$iUrJ7Ahh^_@#Z0Hl+4m&A8dlRD!Y{?fW@0u_wV6;!M6zLh*dy(qkTDxruP5JJ{(u zm5`U7_k`W@O0GHoeW1O1nZ zOXW|}Mk5Y22XjC%I?lt-!8mXmNc39Eruqgtq)T&-PWO?Bw%H#wTu&GoXE8h$`7ZD} z@STO)Ab&IfMb%OIY@*cBL02AoBm){{W~71RM5Vn>Lzj0RpJz)s=k1i1ki=Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS?{7FPXRCodHn|Y`eRUF5Cx#5zP z1-WFtB5gO7C=*i(Bt*=AibN|VXj3a~v6O-ci|mhxAR|m)Dp)~;B?=Xiy;dqUHOov> zGq=i2O-*y@^R0LB%+E9D&b&MG-o5gE@MY%rJHPFmJ7=3Yw^_3$YHER|7HDdLrWPpM z7N}~B%#Iy9){3}SgTA0AxDa#$r`Dkj*Zp8G*aJ3!AHZ7hHCS3zRdtx_$wM^C*A zAM69A&>oBzf^p!iiftv5uL8rtB5)YwL5Fa<01N|-(j!v;KqT56j0CGdLz3c+0?kt= z9b=Gri<6wjmgzv_OH$f_;yUmL(71B|v;!KGI)WY`O;=ih{&>czPq>x`(J<}6E8r*y zk-AzfcoGZ(rzNQYdL6-a;3@DiNYZ6zqj!1||GDarL@%%gglIK|4}s2EB!iz$U?Nxv zLbQQGJ=Kjv1XrIw0ODv91*5?!d1Q!RO$4`qA3+>xARm`U{Gd;Q>WPT!QakI)TL+zF zR7k9rU@X`U;^>)-!WDNz22aOjfqV`~G`19vlum=V?ZFEmj%HAh`Q#MIk^m3KL_eak zh;kz_Xg^hU zL|)y1Z>G~S;o8g+##sm8n<@0Uv{!jRWbCtf^ERk zW&~P@mQFaTvEJeJE8LL8J9#7^oIv56a`=Y)J= zm&qXQ#=xicZ{Gt;dXkb8){CtN_?we^h-zZ1!M?$#`DhmZbL4Rku#|j-jb%4rXRc+w zV3jDNZf(I{;F3NJL?|>!k3!RK>Sji)E12PJqrRHFXR6SX){5*1LJeg1Rfll)hH+RH zES1tKe>&I*eg$uV>IBKXs{}CJ1;e$^+dYa9&zjJA^ zThF*Ic7>}{cmJVBRuE0&#`l6u3(WfqN;zEz2KThUP~D9STp?Qlme?&pV$DDMs$Wsp{0#IEl&FWdRR zC4J=$6WaS-3+{t2wd4(*YS7@*e7GjXOUZc&aA~b;)xu?*d!65LNsGiFF-C1f;ijNc znHAD18e;5>z12-KZVb`^0+-sm%t>^A8Fh)wTJWE_^-J17I%RP(lJAL+G?2H_JbF53 zqcWd>o#lM z{kbPZ22I zvpw~aXa#7SDjN*!hrUh7DsCJi=T<=PpEm*@=^RtCuI08MMl~L9gIt|*z9;v~!QCsE1zM*Plpi8nEx8A+ z>?0lbNHD!j_kF3bdH8t!fa`z`lIs5(t&V$6e-}Fj69yV?DpDL<@i&qih8e^Z4oxEPa*OL1QYCwPpt&X=PfSRc`qD+!G|9sXD8q<%gs- z9xe1FFVXMd`Yht%XOtWonwN#|+Ycv6MWppK5%H9bAgf2Dc?)4cv#6c?^Alyk6Z7yM7*@_cnMX zOASaR^r~UIr!uZcU2-(g?mH2odnK@x_i>s;xusU37TVa>+S+({{e5#0m<05Mc-K(K zwI8bimP+cjX)BiL(w&;f-zcEtwC;PPVtH*vK_^JGr}_&V2HM8x%co2FyLcxSuG)uH zF40i!!DC<>$dV>kZmW1Qr)4zL-37kPpp`T$ras~CNvk|XRPF+xP3Wf}H0x1(0=Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS>xJg7oRCodHn`?+wRTRg)sUtIE zR%4L)Xe4ramqnC`DFqS|)|UctD5Vd*=wS~krJxT6+4qbnol+=*3MuMC66rt>dYM{a zrlpmZy-dq|G}H9^!@c946Se*bjDsufSIDiIB_X`nfg^5tLKF zBJegi0LrC(2u^H>$lyp0TnF9)eIN;XDD%M~3d6yCusMl{7#-7U8KA_+Ae_gb+{R>i}1V z@TQIj!!H0^KpcHZ;r-y$)HzU1gK)ST90XCclY#}{xN6#wO5HfE77^8@e#@7SN~Q7D zHVWq-2T`<&f}pXb+IH4OKh8f85t)9K)y1f^R7wDD0={nb2l;c-VrO0KAOKUrAz*1c z8Cp;Me~AE$0bkq5kXFk%D;hst*5>K4}#%wvMSH>iGN=lZ(YkUt_N7sOW)NY zhQW6Y&=_TDb(}oRt6hOO-nx}xpq{*M+_@*zDCEC$9X0nee0t!SVfY4oe09ykz!5;r z+tPEPh9NlF3Y+v2pDuWo7`~bZDCF(-MvOn#IPeSU`%GRX$(lP}iLrySJUtDNTkTUM zeb*pU;0-cbazs%!yBOZg^LV70Y-C_u2HB8_8l+bZGI?&0OYb0!aqj?2H+cLA%0f}& zO!GK13D}wIv!F;c5L4VB-Ho4i$8kji`CgeTw4U|ArNbn~R;IN|O(0(pTO=ifTdn(i7`bs|yrc-v9YntgqW89Ek%Mqrqkkt7dmyWmz-#vlYLH_l=vb5&WY}7#PjJ?~n zH>w5M7BkuvYM}e`@Wr;E_g()&17y3Lt0T+zz7{_uKwjr)diGq;1}|fVGx2dO*biLN z^6Dhlt*92HvpOzyA!t|jZh02(mtwT-8P7A8?k(yJ!Fa+AYySSUqJkM=z@Ixk{^=9e z=|L{QxX`0uUXXCgnegjo(C_i@*Gy5;F@a3h(9_3_kzbSWo-m)C0T=j{m`ec z5}6x^u(<`?2DC@zBb{Rk>soFE5$f@1o8|JP`5xQP2akXsJbo0iw4}PcEI$yOQ_$jE zd&*K)Wg+a-0Z)CVz7;$Lz5&H(0}Mqcp2#kPuuffk58OkST34OTRQPR`eIBA7Tc(pS z7fb--fHvp!cCTq#+qz1Jl73-W2^Qgpes?IJFl-sH^iug6OOvExou2*N8c;#{b!5*e z&59UqluZDKj6wQVc4>@QB1P135vb&!j)K{HxmgL+3X>-k>+6K2-sEdKs*%caz;~j= z+Tly<0d502NIDm^9MxRd7kX=Q>;A76|kf-Kf%KsR_7NYlFU`c1Pi$2icN|I#6u#rH& z5?IZPY!QeEyI)SB+gB8@15vw&j_(*T2lasOyT_1QVsm@fLl+n_I(Hf85^cb(K zU%^#L)Q2AZMP%v4By?9@2UfR&b=LZPx{s@7oS^Y7%2?#}AT$ZMq?xm{ZHcG~s-2Ia zqreK+dUL;t^tF}Pf&5aVQ_0zt=&ZRc25aCxBFiJ_L-Nb&cF5^du%+8;?qsDE;(@jr zezKmJw7TR15PYZ#-b;X`Y#yh<3oUGWtv8;ue&5u8^!kxSEyVi{MZVT!J-|{$-L}-m zkm##Bo=9IecoMk#NX6{h4TDaQXifDO=mT2D=*y=|`W<{6FRogLWtRxlXz(!j5hO{A zvl|tUz>BEkfS|akC!9$I#2@(|RtoD6A1wD*8uW@ZsGXl*BG+qS$1FmC=d(qo&dH?_b07*qo IM6N<$f?qjupa1{> literal 0 HcmV?d00001 diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-xxhdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-xxhdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_change.png new file mode 100644 index 0000000000000000000000000000000000000000..5d35379ea8f7fee3d2d5dc40ceee3ddcb73e7477 GIT binary patch literal 2097 zcmV-12+sG3P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS?n@L1LRCodHn_q|*RTRhf511%E zR4x@_DW(>tI2lnbic5kTrC2E7$_ogH>Pw zXeZaH{0W=|pMpjFgK@r|7*nJ1ig9{)Xm^p0>*ef|-3)X?VK%Puv@F94OaY_UH z{1B3}30wm0WQxjhum@}aMUptvLD?p4)K(ngYA1?i)4a$If$RW(w~2O=x_v-bLnR`v zgj3uhQA|53aae`~=L6tiC_3~vz$mz{41bX};!b?XS4b4&KoP#mY;d>)91BH+{wR2; zGKV=t@|F1H;EH0^M6`avk*=Ija;{VNQvFf*9^@M+22T`o{Z|rBLbugr>NfkK&z@E> z0L9|T!CE81qXuM8zCpR7R_77qiUlYpPwE-C@uWw&_q0+VvvYsPB}wC?mn8L}+9?2p zL*N%+MVIotxpHj&6dUkvH_ekYv8_fRI}EI7Fr4!-C$EQ!5qJal;k>r0&z;ReuJz4H z$M$8W^Y4qK6M=st?VkeL`nW&gy2w#m9LMo-Cef8X;6qQ=_Y8rSB~QYC%IM>YkZTcW zr$AXz+ht`s zMLSI~O5CQ(GMt!Q(|5>-$> z6x%Vy4%7!Lt7Ey8pb^VLd0#9MZSs<%fXBdFU>A5XIhW4s4C;oINs@LJtc=9=O9`4V zEK`)Dwk)vMZ50yDPqya;CL7?*Wm4X#+l@xrDp6muGLaWYQ#~!$WLqca<4s061=?sp zzUlBtRcH>9b)hx^F8PQWxUnC1xb()Qn9$h!<@Xe8{ht*ap{Lc}7@n*xoO_*)NfkAh z!CpI)R*GMVv^-*4Q{Ipbw%s|ln&)^DedSm`kcO_L!t*3JwB>8%i1igL)AF2Y{Tt=n zS$9f^ttNI>D%(Vd*c+2hr2g}cwAUWD`jnM(dF^KEX)y@?$+qM?cKq>X$hiY@p#U)= z9u3@9t`%)BI~v<@NPQl(90OKCSx+kaI{3U}=c;g`OMS7aoMg@OvC)+-CR~3Rg2jn% zqYf5rpVa4;r?i(KZyP}Gt%`~ko>soFiVDh~I~<;G$81LB^{J)rUV^;MuRlUw9KBZM zR=%`~3d$a*=R4#|FDk9H^u1_;V(#yB%OdN%j;}F(%sNQU3qNVGFP$LAZ^tU{hv<~l zTNB1)@_L8klA{Z$ z7C9A#668(jS{{E6d8#^|o@9*zwNd!34whmm&$>G7w}-m;=kPzp)1 zhdgPF7cocKZgi!K3D+GC!Bs~WQaxZQrYU=meq%Fm*_QlLN_cT;6=(PC>caYE2- z+a2kJp!HNJd5v@h`se+qjW$gu5Ufo-W{%@cMmYuA&DMrlCd8T3{p~`-Vj(zh8&NL4 zVI~JOm@p*Tri^)-g|5VuwyG`HlrKH%)z0%?lF)0X;sapiYtLS~{!j%BBhi6@M zdfn*S7U9vx`mQ!cdg5s@tF=|SB+;*_xzpodF$jsqw0pqQj)A5dAA#?Io=_TdUIF5? z@+|#|dl^c{y5hADajpk>Z$B^z%4arPh09Rt)r*zU!UP#ZNHp+=Hu0^Gc4cui?H^Nq zu3dvRbw5+LJQHTzDUG}4)ibd^1FnFgqA~W7xQsZ~kaW$*3&gq{yaVihGpdGMu?cj|N1Su=%aEWQz>|6P8StDWCv{484tg0vr`v6F zYIoZnNx}d)20YQgtq&$|Zy^awKqyH{+^qgH%e?$GNP@1U(CwxqX;nQ6yw@}HvQM=H zMFKQ%drvpiGopoLrT|cOc=M#03?+Z2IO>ZEeY_O)FPU}5p2uyM4|(>% zdOAHsu6*MODC$nH%WUQzx3@#ldYb)3S z^qy@MSO7YeuOJxa2eDtBb;?_4Fzwh$h=7C*QnwOlfY--MLTtjiYmlacJ?Ukjmw{de bie}(nq*@VI><^}<00000NkvXXu0mjfL~7M8 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_set.png new file mode 100644 index 0000000000000000000000000000000000000000..f3fb0a53aa8881628423de9d8e7728246907cc79 GIT binary patch literal 2281 zcmVPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS@Q%OWYRCodHn_Y-iRTRf(G&K~F zN}-U-kJLz%B!UK0NP{Q{Dh#3r6G;(z(V&DLC$hw%-g1(W=uIdD%Y3jgm=Fseq%6U* zF@#XCqz@<3nwft8@to^E>#lRp$DBJe*Ie-D?7jA0|F!m-bN1PLpF3@B*X4Q!u4mwS z2F5M}?PKS~gC1TJlVMmW#)bbEXIfRtk)qnaQRvXDWp0uO;DU_O`( z8p&lEe+0+D=im?t`=0ByAtYr1=mdSBDiN1B7qo1a2!0jl0nHZq&|TRYLa@uhk!EMb z;g`?lRcEQPIf&pi(QXIpKpx%;^!pB+1gAkfF;lEf*mEf_0*k@TAWMem@IKheJf#VK zdd;-{!79IM3K^M5K41XRQaYsJnD@_#Rggkte^}*qEusV{hkSi9Tm^^9D#EmDt%DuOh0vVm>yI7JmPkKqx7^+o5!V^6I^sBhk7JRp^aUS!v%Y5tv@KZy|6!vqR)t)f zKr4HTu_Sv#whSBu7cH? z85DL}OnNKs@<$~QdgnP^B?H_9-vAh?h+|X97_{}V(o=>@caKg2t@NWPytl%p+Y(h! z?=Ctp#SSzED+`KpDM6iP9WH%w$tM_lfBDV%tgrNfBkgUqr3g>h7tSrtz@#d) zmZ85+CavVZ6S3T5t*I{!gKbo%uhu!96uxt;A4t>gq}=NyICSJ|WsmihTF3H)vHq2M z=Bhg;q^}lsRw_G0huE8w4#xhouGs60TVo34M3&ufI~EhcrO=Xc(fP+)A!km=xdNmU z@o3_0dfQj^7chyg$T9 zNxePcO$A5?^Yrxs&z0E*1xRmn`qn)u%}9_=0mk zU7BjD(~v7c-h!^~_2-bsssnK$xIPe+t12#bh`x1nX{uYDhPs!LcL(Y9r=PurqMxAT zlIRS%-*leJ8fA^qm99oyQyhZd99^2~PSY?%-Fx+$Zd3`N6}K9MJ@iifXnYNQkINts zZ|-dK?jSK9H?;cklK0G;Znf&mwbIqXOoFLovkK+RtF(#Iy@^^%g*a}Z$v&d__G03M zpw*5$;u}HxskG$P(v>nk?~huuNfaPh6nhM=y@^g473@aqz$^%HxcGXb(CDF^{3>8K ztN9Pif|i@eR!?!=h0sw3B!FTU#2&a;h@6pe2J{a%ZVzRv1j*N$OlWE@_$ z)pg8JVB8%NIAtA;=zu;xv|k^UrSpzWP}fAVR)vQa;`4WpL$ z>_ePOK-$-j$KAmNN^Bnts>O;J>#t~~s~F3b-jHbGAFyO4>f%V8A5(uOg(tCJqt7Iu z4-%8&F;K2MB#YZJuNb$?r)Oe)0$cz!2?vOBKKLnW)OB9iUb+lX%lvqOSZ@b!f#LJ! zaM0*>f>7QK+e?>WTn_XGv$CNyX*tlp=VmiPfxJT}HqDnV&mjhHvSZl!Q8u0&T&bRXe(j?rIJ)m#Z;hpr=#r@$pM zdM)esk)*n_T+^>*tGN=S(UGJhTsAr*)h1S-nddldEw9R*AdQqHeZb{SXVgm4QIfRM zX=`cK4JD%2d~^?Z%-HI2`-~*LKq7aUwx(C{t2uEIn3CdbhSAT!=02l~tC~tqGLC;@ zMWHLi)4_g_CZqk&Eb|B?UIeDaR8&8*#U$Re(c96$t9I30AhFyp^q0ul86S2L*dVMz zO*;$CL1DbyeuLm8bk70%c2igFaWtu)BBV{*g~I=mnUxGU zoA!vcXF1Q?PLTTWza6Xtd3fzV_3D$$Md00ysB7{IrC#pdL_hpzP10{;x1z=Z2jv%o zdRP>9`AIrtvSk9*-p$+KqOMGi!Q_4Tv*Fb0^l$1`qvj~9z+d(-=%C-j;80folI{9> z@pMVsLT05W=`1fKsRyj4pAN%c1^GV8Wf5P??cC-%&C|)Eek7`olln|kMn>%sE3=X= z{Ws)}((i 0.0 ? 1.0 : -1.0) * (1.0 - effectFraction), -65.0) * deltaTime * dp * particleFraction; - particleTime = max(0.0, particleTime - 1.2 * deltaTime * effectFraction); + particleTime = max(0.0, particleTime - 1.2 * deltaTime * particleFraction); outUV = uv; outPosition = position; diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 6fabeb56a..bdae9611f 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -4482,4 +4482,5 @@ \'ذكّرني بتاريخ\' d MMM \'عند\' HH:mm \'ذكّرني بتاريخ\' d MMM yyyy \'عند\' HH:mm Menu + ارسلت من diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index ae7237aba..ae0d62ed2 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -679,6 +679,12 @@ Removed by %1$s User Permissions What can this user do? + What can %1$s selected users do? + What can %1$s selected user do? + What can %1$s selected users do? + What can %1$s selected users do? + What can %1$s selected users do? + What can %1$s selected users do? Read Messages Send Messages Send Polls @@ -882,8 +888,8 @@ All actions Selected actions All admins - **No actions here yet**\n\nThe group\'s members and admins\nhave not taken any service actions\nin the last 48 hours. - **No actions here yet**\n\nThe channel\'s admins\nhave not taken any service actions\nin the last 48 hours. + **No actions here yet**\n\nThe group\'s members and admins have not taken any service actions in the last **48** hours. + **No actions here yet**\n\nThe channel\'s admins have not taken any service actions in the last **48** hours. **No actions found**\n\nNo recent actions that match your query\nhave been found. No recent actions that contain \'**%1$s**\' have been found. What is the Recent Actions? @@ -916,6 +922,12 @@ un1 stopped the poll: un1 stopped the quiz: un1 deleted this message: + un1 deleted message from %2$s + un1 deleted %1$d messages from %2$s + un1 deleted message from %2$s: + un1 deleted %1$d messages from %2$s: + Hide all + Show all un1 changed group location to \"%1$s\" un1 removed group location transferred ownership to %1$s @@ -983,6 +995,16 @@ Edited messages Pinned messages Leaving members + Members left the Group + Members And Admins + Apply Filter + New Admin Rights + Messages + Group Settings + Channel Settings + Filter actions by type + Filter actions by admins + Show Actions by All Admins Voice chats Invite links un1 set the slow mode timer to %1$s @@ -1259,7 +1281,10 @@ 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? - Ban user + Ban %1$s + Ban users + Restrict %1$s + Restrict users Report spam Translate Hide Translation @@ -1268,6 +1293,38 @@ Translation failed. Try again later. Translation failed. Delete all from %1$s + Delete all from users + Delete %1$d Messages? + Delete %1$d Message? + Delete %1$d Messages? + Delete %1$d Messages? + Delete %1$d Messages? + Delete %1$d Messages? + Additional actions + Fully ban users + Fully ban this user + Partially restrict users + Partially restrict this user + Proceed + Messages Deleted + %1$d users reported for spam. + %1$d user reported for spam. + %1$d users reported for spam. + %1$d users reported for spam. + %1$d users reported for spam. + %1$d users reported for spam. + %1$d users banned. + %1$d user banned. + %1$d users banned. + %1$d users banned. + %1$d users banned. + %1$d users banned. + %1$d users restricted. + %1$d user restricted. + %1$d users restricted. + %1$d users restricted. + %1$d users restricted. + %1$d users restricted. Clear recent emoji Do you want to clear all your recent emoji? Clear recent statuses @@ -1969,6 +2026,7 @@ Set emoji that corresponds to your sticker Choose a name for your pack. Sticker added to %1$s sticker set. + Sticker edited in %1$s sticker set. Stickers removed. %1$s is no longer in your stickers. Masks removed. @@ -2446,7 +2504,7 @@ Save to Gallery Sound muted Edit Name - Edit Profile Color + Change profile color Customize Custom Enable Custom Notifications @@ -2538,6 +2596,10 @@ Cut Out Cut an Object Undo Cut + Undo + Add Outline + Erase + Restore edit Paste from clipboard Proxy Settings @@ -2594,6 +2656,7 @@ Groups Channels Stories + Reactions Please note that **%1$s** are listed as exceptions and won\'t be affected by this change. Please note that **%1$s** is listed as an exception and won\'t be affected by this change. View Exceptions @@ -2698,6 +2761,7 @@ Stickers & Emoji Profile Photos Miscellaneous + Logs Photos Voice messages Videos @@ -3122,6 +3186,8 @@ Share My Live Location for... Share my Live Location Stop Sharing Location + Sharing Location... + tap to add more time Stop location sharing Do you want to stop sharing your live location with **%1$s**? Do you want to stop sharing your live location with **%1$s**? @@ -3142,6 +3208,7 @@ for 15 minutes for 1 hour for 8 hours + until I turn it off updated updated %1$s updated just now @@ -3151,6 +3218,8 @@ %1$s sharing with %2$s STOP ALL You are sharing your Live Location with %1$s + Add More Time + For how long do you want to extend sharing your location? Choose for how long %1$s will see your accurate location. Choose for how long people in this chat will see your live location. Enable GPS @@ -3734,6 +3803,8 @@ Call Video Call Copy + Restrict + Ban Rename Delete Start @@ -5618,6 +5689,11 @@ Release to go to the next unread folder Pull up to go to archived channels Release to go to archived channels + Pull up to go to next channel + Release to go to next channel + Pull up to go to the next unread topic + Release to go to the next unread topic + No more unread topics in %1$s You have no unread channels Favorites @@ -5861,6 +5937,7 @@ Nobody viewed QR Code + New reaction to your message %2$s to your "%3$s" %2$s to your message %2$s to your photo @@ -5893,6 +5970,8 @@ %3$s to your game in %2$s %3$s to your invoice in %2$s %3$s to your GIF in %2$s + %2$s to your story + New reaction to your story Blur in chat Allow background activity @@ -5959,6 +6038,7 @@ Groups Sound Channels Sound Stories Sound + Reactions Sound Too long Too large Invalid format @@ -7019,9 +7099,10 @@ Message sent. Just now Expired story - Stories + Posts + Archived Posts Reaction sent. - My Stories + My Profile Saved %d saved stories %d saved story @@ -7148,6 +7229,7 @@ Close Friends Failed to process video file. Preparing video… + Preparing sticker… No saved stories No posts yet… Publish photos and videos to display on your profile page @@ -7421,6 +7503,7 @@ Hide My View Stealth Mode Subscribe to Telegram Premium to hide the fact that you viewed peoples’ stories from them. + View\nAnonymously Hide Recent Views Hide my views in the last 5 minutes. Hide Next Views @@ -7428,6 +7511,7 @@ Unlock Stealth Mode Turn Stealth Mode on to hide the fact that you viewed peoples’ stories from them. Enable Stealth Mode + Enable and open the story Available in %s Stealth Mode On The creators of stories you viewed in the last 5 minutes or will view in the next 25 minutes won’t see you in viewers’ lists. @@ -7447,6 +7531,10 @@ Update Reactions Level %1$d Required Level %1$d Required + Maximum number of reactions + %d reaction per post + %d reactions per post + Limit the number of different reactions that can be added to a post, including already published ones. Your channel needs to reach Level **%2$d** to add **%1$d** custom emoji as reactions. Your channel needs to reach Level **%2$d** to add **%1$d** custom emoji as reactions. Your channel needs to reach Level **%2$d** to add **%1$d** custom emoji as reactions.\n\nAsk your **Premium** subscribers to boost your channel with this link: @@ -8203,6 +8291,8 @@ Group Emoji Pack Group Emoji Choose an emoji pack that will be available to all members within the group. + Group Sticker Pack + You can choose a sticker set that will be shown to all group members. Channel Emoji Status Group Emoji Status Choose a status that will be shown next to the channel\'s name. @@ -8462,6 +8552,12 @@ You have changed the business location. Apply changes? Remove Location Are you sure you want to remove business location? + Remove Hours + Are you sure you want to remove business opening hours? + Remove date of birth + Are you sure you want to remove date of birth from your profile? + Remove channel + Are you sure you want to remove channel from your profile? New Greeting Message Create greetings that will be automatically sent to new customers. Add a Greeting @@ -8564,6 +8660,7 @@ Telegram shares %1$d%% of the revenue from ads displayed in your channel. **Learn more >** Available balance You can collect your reward using Fragment, a third-party platform used by advertisers to pay for ads. **Learn more >** + https://telegram.org/tos/content-creator-rewards In the coming weeks you will be able to collect your reward using Fragment, a third-party platform used by advertisers to pay ads. **Learn more >** Transaction history Show %d more transaction @@ -8623,6 +8720,9 @@ **Remove date of birth.** Date of Birth Save + Change Opening Hours + Change Location + Channel %1$s %2$s (%1$d years old) 🎂 %1$s @@ -8637,6 +8737,7 @@ Date of birth added. Oops Sorry, you can’t change your birthday so often. + Add Your Birthday Add your birthday! 🎂 Let your contacts know when you’re celebrating You can always set your birthday in profile settings. @@ -8674,4 +8775,98 @@ Invite via Link You can send an invite link to the group in a private message instead. You can send these people an invite link to the group in a private message instead. + Replace number + Copy username + Change username + Set username + Edit bio + Copy hours + Edit hours + Remove + Copy address + View location + Open in Maps + Change location + Remove + Change + Copy link to profile + Copy Link + Change Channel + Ads in Channels + Do Not Hide Ads + As a Premium subscriber, you don’t see any ads on Telegram, but you can turn them on, for example, to view your own ads that you launched on the **Telegram Ad Platform >** + Channels + %d story deleted + %d stories deleted + ⚠️ Your Premium subscription is expiring! + Don’t lose access to exclusive features. + Access to Telegram Premium is expiring! + ⚠️ Unfortunately, your latest payment didn’t come through. To keep your access to exclusive features, please renew the subscription. + Restore Subscription + Channels you joined + Recommended Channels + Channels + VIEW STICKERS + VIEW EMOJI + Story pinned + %d stories pinned + Story unpinned. + %d stories unpinned. + Now it will be always shown on the top. + Now they will be always shown on the top. + You can’t pin more than %d posts. + Reactions + Messages + Stories + Notify me about… + New Messages in Private Chats + New Stories + Important Stories + New Messages in Groups + New Messages in Channels + Reactions to My Messages + Reactions to My Stories + From My Contacts + From Everyone + Off + More Options + Less Options + Notify about reactions from + My Contacts + Everyone + Create + No channels yet… + You are not subscribed to any channel. + Set Intro Sticker + Enter word from SMS + We’ve sent an SMS with a secret word that starts with “**%2$s**” to your phone **%1$s**. + We’ve sent an SMS with a secret word to your phone **%1$s**. + Secret word + Enter Word from SMS + You can copy and paste the word here. + Incorrect, please try again + Incorrect word + Enter phrase from SMS + We’ve sent an SMS with a secret phrase to your phone **%1$s**. + We’ve sent an SMS with a secret phrase that starts with “**%2$s**” to your phone **%1$s**. + Secret phrase + You can copy and paste the phrase here. + Enter Phrase from SMS + Incorrect, please try again + Incorrect word + Request another SMS + < Back to entering the word + < Back to entering the phrase + < Back to entering the code + Return to entering the code > + Return to entering the word > + Return to entering the word > + You can request another\nSMS in %1$d:%2$02d + Telegram can call you in %1$d:%2$02d + Forwarded from + Restricted **%s** from sending any messages + Show %d More Message + Show %d More Messages + **No results found** + **No results matching your filters** \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 203bb5380..fa9050af5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,8 +13,8 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Sat Mar 12 05:53:50 MSK 2016 -APP_VERSION_CODE=4583 -APP_VERSION_NAME=10.10.1 +APP_VERSION_CODE=4710 +APP_VERSION_NAME=10.12.0 APP_PACKAGE=org.telegram.messenger RELEASE_KEY_PASSWORD=android RELEASE_KEY_ALIAS=androidkey