From 9b78d437de6ec1bbf067e2f17221b38db49f064d Mon Sep 17 00:00:00 2001 From: dkaraush Date: Fri, 18 Oct 2024 00:04:16 +0400 Subject: [PATCH] update to 11.2.3 (5335) --- TMessagesProj/build.gradle | 8 +- TMessagesProj/jni/TgNetWrapper.cpp | 6 +- .../jni/tgnet/ConnectionsManager.cpp | 30 +- TMessagesProj/jni/tgnet/Datacenter.cpp | 4 +- TMessagesProj/jni/tgnet/Defines.h | 2 +- TMessagesProj/jni/tgnet/Handshake.cpp | 4 +- TMessagesProj/jni/tgnet/Request.cpp | 4 +- TMessagesProj/jni/tgnet/Request.h | 2 +- TMessagesProj/src/main/AndroidManifest.xml | 8 + .../src/main/assets/darkblue.attheme | 1 + TMessagesProj/src/main/assets/night.attheme | 1 + .../recyclerview/widget/AdapterHelper.java | 39 + .../widget/DefaultItemAnimator.java | 37 +- .../recyclerview/widget/RecyclerView.java | 14 +- .../exoplayer2/mediacodec/MediaCodecUtil.java | 2 +- .../exoplayer2/source/hls/HlsMediaChunk.java | 2 +- .../exoplayer2/upstream/AssetDataSource.java | 2 + .../exoplayer2/upstream/BaseDataSource.java | 3 + .../android/exoplayer2/upstream/DataSpec.java | 2 +- .../DefaultHttpDataSourceFactory.java | 2 +- .../telegram/messenger/AndroidUtilities.java | 50 +- .../telegram/messenger/ApplicationLoader.java | 19 +- .../org/telegram/messenger/BuildVars.java | 5 + .../org/telegram/messenger/ChatObject.java | 12 + .../telegram/messenger/CopyCodeReceiver.java | 15 + .../messenger/DatabaseMigrationHelper.java | 13 + .../org/telegram/messenger/DialogObject.java | 3 + .../messenger/FactCheckController.java | 10 +- .../telegram/messenger/FileLoadOperation.java | 20 +- .../org/telegram/messenger/FileLoader.java | 16 +- .../java/org/telegram/messenger/FileLog.java | 33 +- .../telegram/messenger/FileRefController.java | 69 +- .../messenger/FileStreamLoadOperation.java | 27 +- .../messenger/FileUploadOperation.java | 4 + .../org/telegram/messenger/ImageReceiver.java | 6 +- .../telegram/messenger/MediaController.java | 77 +- .../messenger/MediaDataController.java | 37 +- .../org/telegram/messenger/MessageObject.java | 101 +- .../messenger/MessagesController.java | 93 +- .../telegram/messenger/MessagesStorage.java | 5 +- .../messenger/NotificationCenter.java | 23 +- .../messenger/NotificationsController.java | 669 +++--- .../messenger/PushListenerController.java | 7 + .../messenger/SendMessagesHelper.java | 13 +- .../org/telegram/messenger/SharedConfig.java | 19 +- .../org/telegram/messenger/UserConfig.java | 13 +- .../org/telegram/messenger/UserObject.java | 4 + .../messenger/VideoEncodingService.java | 5 +- .../ExtendedDefaultDataSource.java | 95 +- .../ExtendedDefaultDataSourceFactory.java | 11 +- .../telegram/messenger/voip/VoIPService.java | 6 + .../telegram/tgnet/ConnectionsManager.java | 33 +- .../tgnet/RequestDelegateInternal.java | 2 +- .../main/java/org/telegram/tgnet/TLRPC.java | 2028 ++++++----------- .../java/org/telegram/tgnet/tl/TL_stars.java | 1785 +++++++++++++++ .../org/telegram/tgnet/tl/TL_stories.java | 8 +- .../org/telegram/ui/ActionBar/ActionBar.java | 14 - .../ui/ActionBar/ActionBarMenuItem.java | 6 +- .../ui/ActionBar/ActionBarMenuSubItem.java | 7 +- .../ui/ActionBar/ActionBarPopupWindow.java | 1 + .../telegram/ui/ActionBar/AlertDialog.java | 12 +- .../telegram/ui/ActionBar/BottomSheet.java | 10 +- .../ui/ActionBar/BottomSheetTabDialog.java | 13 +- .../ui/ActionBar/BottomSheetTabsOverlay.java | 133 +- .../ui/ActionBar/DrawerLayoutContainer.java | 2 +- .../java/org/telegram/ui/ActionBar/Theme.java | 7 + .../telegram/ui/ActionBar/ThemeColors.java | 8 + .../telegram/ui/Adapters/ContactsAdapter.java | 2 +- .../telegram/ui/Adapters/MentionsAdapter.java | 22 +- .../ui/Business/BusinessIntroActivity.java | 4 +- .../org/telegram/ui/Cells/ChatActionCell.java | 734 ++++-- .../telegram/ui/Cells/ChatMessageCell.java | 163 +- .../org/telegram/ui/Cells/DialogCell.java | 20 +- .../telegram/ui/Cells/EditEmojiTextCell.java | 287 +++ .../org/telegram/ui/Cells/EditTextCell.java | 55 +- .../telegram/ui/Cells/ProfileChannelCell.java | 2 +- .../telegram/ui/Cells/ProfileSearchCell.java | 2 + .../org/telegram/ui/Cells/SessionCell.java | 4 + .../org/telegram/ui/Cells/SharedLinkCell.java | 4 +- .../java/org/telegram/ui/Cells/UserCell.java | 2 +- .../telegram/ui/ChannelAdminLogActivity.java | 2 +- .../ui/ChannelMonetizationLayout.java | 15 +- .../java/org/telegram/ui/ChatActivity.java | 490 ++-- .../telegram/ui/ChatPullingDownDrawable.java | 1 + .../telegram/ui/ChatRightsEditActivity.java | 3 + .../org/telegram/ui/ChatUsersActivity.java | 12 +- .../ui/ChooseDownloadQualityLayout.java | 100 + .../org/telegram/ui/ChooseQualityLayout.java | 196 ++ .../telegram/ui/Components/AlertsCreator.java | 429 ++-- .../ui/Components/AnimationProperties.java | 13 + .../BottomSheetWithRecyclerListView.java | 284 ++- .../org/telegram/ui/Components/Bulletin.java | 8 + .../ui/Components/BulletinFactory.java | 23 + .../telegram/ui/Components/ButtonSpan.java | 140 ++ .../ui/Components/ChatActivityEnterView.java | 19 +- .../ui/Components/ChatActivityInterface.java | 4 + .../ui/Components/ChatAvatarContainer.java | 23 +- .../ui/Components/ChatGreetingsView.java | 12 +- .../ui/Components/ContactsEmptyView.java | 122 +- .../CreateGroupCallBottomSheet.java | 31 +- .../CreateRtmpStreamBottomSheet.java | 183 ++ .../Components/DeleteMessagesBottomSheet.java | 9 + .../telegram/ui/Components/EditTextEmoji.java | 20 + .../ui/Components/FlickerLoadingView.java | 25 +- .../telegram/ui/Components/ImageUpdater.java | 3 +- .../ui/Components/InstantCameraView.java | 10 +- .../ui/Components/InviteLinkBottomSheet.java | 10 +- .../telegram/ui/Components/ItemOptions.java | 3 + .../telegram/ui/Components/JoinCallAlert.java | 10 +- .../telegram/ui/Components/LayoutHelper.java | 6 + .../ui/Components/LinkSpanDrawable.java | 10 + .../telegram/ui/Components/LoadingSpan.java | 10 +- .../Paint/Views/StickerMakerView.java | 5 +- .../ui/Components/PermissionRequest.java | 2 +- .../Premium/GiftPremiumBottomSheet.java | 44 +- .../Premium/PremiumLockIconView.java | 4 + .../Premium/boosts/BoostDialogs.java | 2 +- .../Premium/boosts/BoostRepository.java | 71 +- .../boosts/BoostViaGiftsBottomSheet.java | 34 +- .../PremiumPreviewGiftSentBottomSheet.java | 115 +- .../PremiumPreviewGiftToUsersBottomSheet.java | 414 ---- .../boosts/UserSelectorBottomSheet.java | 68 +- .../Premium/boosts/adapters/BoostAdapter.java | 7 +- .../boosts/cells/StarGiveawayOptionCell.java | 8 +- .../ui/Components/RLottieImageView.java | 7 +- .../Reactions/CustomEmojiReactionsWindow.java | 2 +- .../Components/ReactionsContainerLayout.java | 3 + .../telegram/ui/Components/ReportAlert.java | 153 -- .../Components/ScrollSlidingTextTabStrip.java | 6 +- .../ui/Components/SearchViewPager.java | 6 + .../ui/Components/SharedMediaLayout.java | 69 +- .../Components/SizeNotifierFrameLayout.java | 16 +- .../telegram/ui/Components/StarAppsSheet.java | 4 +- .../ui/Components/StickerEmptyView.java | 6 + .../org/telegram/ui/Components/TableView.java | 157 +- .../java/org/telegram/ui/Components/Text.java | 8 +- .../org/telegram/ui/Components/UItem.java | 10 + .../ui/Components/UniversalRecyclerView.java | 79 +- .../telegram/ui/Components/VideoPlayer.java | 674 +++++- .../ui/Components/ViewPagerFixed.java | 6 + .../ui/Components/spoilers/SpoilerEffect.java | 22 +- .../ui/Components/voip/VoIPHelper.java | 26 +- .../org/telegram/ui/ContactsActivity.java | 5 +- .../java/org/telegram/ui/DialogsActivity.java | 157 +- .../java/org/telegram/ui/Gifts/GiftSheet.java | 1295 +++++++++++ .../ui/Gifts/ProfileGiftsContainer.java | 314 +++ .../org/telegram/ui/Gifts/SendGiftSheet.java | 634 ++++++ .../java/org/telegram/ui/GradientClip.java | 11 + .../telegram/ui/GradientHeaderActivity.java | 37 +- .../org/telegram/ui/GroupCallActivity.java | 431 +++- .../org/telegram/ui/ImageReceiverSpan.java | 13 +- .../java/org/telegram/ui/LaunchActivity.java | 48 +- .../org/telegram/ui/LinkEditActivity.java | 5 +- .../ui/NotificationsSoundActivity.java | 14 +- .../org/telegram/ui/PaymentFormActivity.java | 7 +- .../java/org/telegram/ui/PhotoViewer.java | 304 ++- .../ui/PopupNotificationActivity.java | 4 +- .../java/org/telegram/ui/ProfileActivity.java | 393 ++-- .../org/telegram/ui/ReportAdBottomSheet.java | 489 ---- .../org/telegram/ui/ReportBottomSheet.java | 1035 +++++++++ .../org/telegram/ui/SecretMediaViewer.java | 36 +- .../telegram/ui/Stars/BotStarsActivity.java | 3 +- .../telegram/ui/Stars/BotStarsController.java | 41 +- .../telegram/ui/Stars/ExplainStarsSheet.java | 207 ++ .../telegram/ui/Stars/StarsController.java | 548 ++++- .../telegram/ui/Stars/StarsIntroActivity.java | 1190 +++++++++- .../telegram/ui/Stories/PeerStoriesView.java | 6 +- .../ui/Stories/StoriesController.java | 3 +- .../telegram/ui/Stories/StoryCaptionView.java | 2 +- .../recorder/ButtonWithCounterView.java | 9 + .../ui/Stories/recorder/PaintView.java | 8 +- .../ui/Stories/recorder/StoryLinkSheet.java | 5 +- .../org/telegram/ui/ThemePreviewActivity.java | 2 + .../java/org/telegram/ui/TopicsFragment.java | 61 +- .../org/telegram/ui/UserInfoActivity.java | 10 +- .../java/org/telegram/ui/VoIPFragment.java | 9 +- .../telegram/ui/web/BotWebViewContainer.java | 214 +- .../main/res/drawable-hdpi/menu_unlock.png | Bin 0 -> 753 bytes .../main/res/drawable-mdpi/menu_unlock.png | Bin 0 -> 553 bytes .../main/res/drawable-xhdpi/menu_unlock.png | Bin 0 -> 987 bytes .../main/res/drawable-xxhdpi/menu_unlock.png | Bin 0 -> 1242 bytes .../src/main/res/raw/utyan_empty.json | 1 + .../src/main/res/raw/utyan_streaming.json | 1 + TMessagesProj/src/main/res/values/strings.xml | 183 +- TMessagesProj_App/build.gradle | 2 +- TMessagesProj_AppHuawei/build.gradle | 2 +- TMessagesProj_AppStandalone/build.gradle | 2 +- gradle.properties | 4 +- 188 files changed, 14174 insertions(+), 4848 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/messenger/CopyCodeReceiver.java create mode 100644 TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stars.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/EditEmojiTextCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ChooseDownloadQualityLayout.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ChooseQualityLayout.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonSpan.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/CreateRtmpStreamBottomSheet.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Gifts/GiftSheet.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Gifts/ProfileGiftsContainer.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Gifts/SendGiftSheet.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ReportBottomSheet.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Stars/ExplainStarsSheet.java create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_unlock.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_unlock.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_unlock.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_unlock.png create mode 100644 TMessagesProj/src/main/res/raw/utyan_empty.json create mode 100644 TMessagesProj/src/main/res/raw/utyan_streaming.json diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 9734abd5ae..9ee9a793b5 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -116,7 +116,7 @@ android { minifyEnabled false shrinkResources false multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\"" buildConfigField "String", "APP_CENTER_HASH", "\"\"" @@ -129,7 +129,7 @@ android { jniDebuggable false minifyEnabled true multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\"" buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_PRIVATE") + "\"" @@ -142,7 +142,7 @@ android { jniDebuggable false minifyEnabled true multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\"" buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_PUBLIC") + "\"" @@ -155,7 +155,7 @@ android { jniDebuggable false minifyEnabled true multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\"" buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_HARDCORE") + "\"" diff --git a/TMessagesProj/jni/TgNetWrapper.cpp b/TMessagesProj/jni/TgNetWrapper.cpp index 5c8a8f8bb3..cdb8e10b7e 100644 --- a/TMessagesProj/jni/TgNetWrapper.cpp +++ b/TMessagesProj/jni/TgNetWrapper.cpp @@ -100,7 +100,7 @@ jint getTimeDifference(JNIEnv *env, jclass c, jint instanceNum) { void sendRequest(JNIEnv *env, jclass c, jint instanceNum, jlong object, jint flags, jint datacenterId, jint connectionType, jboolean immediate, jint token) { TL_api_request *request = new TL_api_request(); request->request = (NativeByteBuffer *) (intptr_t) object; - ConnectionsManager::getInstance(instanceNum).sendRequest(request, ([instanceNum, token](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + ConnectionsManager::getInstance(instanceNum).sendRequest(request, ([instanceNum, token](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { TL_api_response *resp = (TL_api_response *) response; jlong ptr = 0; jint errorCode = 0; @@ -117,7 +117,7 @@ void sendRequest(JNIEnv *env, jclass c, jint instanceNum, jlong object, jint fla errorText = jniEnv[instanceNum]->NewStringUTF("UTF-8 ERROR"); } } - jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onRequestComplete, instanceNum, token, ptr, errorCode, errorText, networkType, responseTime, msgId); + jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onRequestComplete, instanceNum, token, ptr, errorCode, errorText, networkType, responseTime, msgId, dcId); if (errorText != nullptr) { jniEnv[instanceNum]->DeleteLocalRef(errorText); } @@ -561,7 +561,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { if (jclass_ConnectionsManager_onRequestClear == 0) { return JNI_FALSE; } - jclass_ConnectionsManager_onRequestComplete = env->GetStaticMethodID(jclass_ConnectionsManager, "onRequestComplete", "(IIJILjava/lang/String;IJJ)V"); + jclass_ConnectionsManager_onRequestComplete = env->GetStaticMethodID(jclass_ConnectionsManager, "onRequestComplete", "(IIJILjava/lang/String;IJJI)V"); if (jclass_ConnectionsManager_onRequestComplete == 0) { return JNI_FALSE; } diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 7965611ebc..958a0710b9 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -624,7 +624,8 @@ void ConnectionsManager::cleanUp(bool resetKeys, int32_t datacenterId) { auto error = new TL_error(); error->code = -1000; error->text = ""; - request->onComplete(nullptr, error, 0, 0, request->messageId); + int32_t dcId = request->datacenterId != DEFAULT_DATACENTER_ID ? request->datacenterId : currentDatacenterId; + request->onComplete(nullptr, error, 0, 0, request->messageId, dcId); delete error; } iter = requestsQueue.erase(iter); @@ -646,7 +647,8 @@ void ConnectionsManager::cleanUp(bool resetKeys, int32_t datacenterId) { auto error = new TL_error(); error->code = -1000; error->text = ""; - request->onComplete(nullptr, error, 0, 0, request->messageId); + int32_t dcId = request->datacenterId != DEFAULT_DATACENTER_ID ? request->datacenterId : currentDatacenterId; + request->onComplete(nullptr, error, 0, 0, request->messageId, dcId); delete error; } DEBUG_D("1) erase request %d 0x%" PRIx64, request->requestToken, request->messageId); @@ -1205,7 +1207,8 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag for (auto iter = runningRequests.begin(); iter != runningRequests.end(); iter++) { Request *request = iter->get(); if (request->respondsToMessageId(requestMid)) { - request->onComplete(response, nullptr, connection->currentNetworkType, timeMessage, requestMid); + int32_t dcId = request->datacenterId != DEFAULT_DATACENTER_ID ? request->datacenterId : currentDatacenterId; + request->onComplete(response, nullptr, connection->currentNetworkType, timeMessage, requestMid, dcId); request->completed = true; DEBUG_D("4) erase request %d 0x%" PRIx64, request->requestToken, request->messageId); runningRequests.erase(iter); @@ -1450,12 +1453,13 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag } if (!discardResponse) { + int32_t dcId = request->datacenterId != DEFAULT_DATACENTER_ID ? request->datacenterId : currentDatacenterId; if (implicitError != nullptr || error2 != nullptr) { isError = true; - request->onComplete(nullptr, implicitError != nullptr ? implicitError : error2, connection->currentNetworkType, timeMessage, request->messageId); + request->onComplete(nullptr, implicitError != nullptr ? implicitError : error2, connection->currentNetworkType, timeMessage, request->messageId, dcId); delete error2; } else { - request->onComplete(response->result.get(), nullptr, connection->currentNetworkType, timeMessage, request->messageId); + request->onComplete(response->result.get(), nullptr, connection->currentNetworkType, timeMessage, request->messageId, dcId); } } @@ -2104,7 +2108,7 @@ bool ConnectionsManager::cancelRequestInternal(int32_t token, int64_t messageId, auto dropAnswer = new TL_rpc_drop_answer(); dropAnswer->req_msg_id = request->messageId; if (onCancelled != nullptr) { - sendRequest(dropAnswer, ([onCancelled](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) -> void { + sendRequest(dropAnswer, ([onCancelled](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) -> void { if (onCancelled != nullptr) { onCancelled(); } @@ -2161,7 +2165,8 @@ void ConnectionsManager::failNotRunningRequest(int32_t token) { auto error = new TL_error(); error->code = -2000; error->text = "CANCELLED_REQUEST"; - request->onComplete(nullptr, error, 0, 0, request->messageId); + int32_t dcId = request->datacenterId != DEFAULT_DATACENTER_ID ? request->datacenterId : currentDatacenterId; + request->onComplete(nullptr, error, 0, 0, request->messageId, dcId); request->cancelled = true; if (LOGS_ENABLED) DEBUG_D("cancelled queued rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name()); @@ -2304,7 +2309,7 @@ void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter, bool requestingSaltsForDc.push_back(id); auto request = new TL_get_future_salts(); request->num = 32; - sendRequest(request, [&, datacenter, id, media](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + sendRequest(request, [&, datacenter, id, media](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { auto iter = std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), id); if (iter != requestingSaltsForDc.end()) { requestingSaltsForDc.erase(iter); @@ -2339,7 +2344,7 @@ void ConnectionsManager::registerForInternalPushUpdates() { request->token_type = 7; request->token = to_string_uint64((uint64_t) pushSessionId); - sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { if (error == nullptr) { registeredForInternalPush = true; if (LOGS_ENABLED) DEBUG_D("registered for internal push"); @@ -2562,7 +2567,8 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t auto error = new TL_error(); error->code = -123; error->text = "RETRY_LIMIT"; - request->onComplete(nullptr, error, connection->currentNetworkType, 0, request->messageId); + int32_t dcId = request->datacenterId != DEFAULT_DATACENTER_ID ? request->datacenterId : currentDatacenterId; + request->onComplete(nullptr, error, connection->currentNetworkType, 0, request->messageId, dcId); delete error; DEBUG_D("12) erase request %d 0x%" PRIx64, request->requestToken, request->messageId); iter = runningRequests.erase(iter); @@ -3273,7 +3279,7 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround, bool } auto request = new TL_help_getConfig(); - sendRequest(request, [&, workaround](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + sendRequest(request, [&, workaround](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { if ((!workaround && !updatingDcSettings) || (workaround && !updatingDcSettingsWorkaround)) { return; } @@ -3422,7 +3428,7 @@ void ConnectionsManager::authorizeOnMovingDatacenter() { auto request = new TL_auth_importAuthorization(); request->id = currentUserId; request->bytes = std::move(movingAuthorization); - sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { if (error == nullptr) { authorizedOnMovingDatacenter(); } else { diff --git a/TMessagesProj/jni/tgnet/Datacenter.cpp b/TMessagesProj/jni/tgnet/Datacenter.cpp index 19d992ffd6..b7e8ea091b 100644 --- a/TMessagesProj/jni/tgnet/Datacenter.cpp +++ b/TMessagesProj/jni/tgnet/Datacenter.cpp @@ -1447,14 +1447,14 @@ void Datacenter::exportAuthorization() { auto request = new TL_auth_exportAuthorization(); request->dc_id = datacenterId; if (LOGS_ENABLED) DEBUG_D("dc%u begin export authorization", datacenterId); - ConnectionsManager::getInstance(instanceNum).sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + ConnectionsManager::getInstance(instanceNum).sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { if (error == nullptr) { auto res = (TL_auth_exportedAuthorization *) response; auto request2 = new TL_auth_importAuthorization(); request2->bytes = std::move(res->bytes); request2->id = res->id; if (LOGS_ENABLED) DEBUG_D("dc%u begin import authorization", datacenterId); - ConnectionsManager::getInstance(instanceNum).sendRequest(request2, [&](TLObject *response2, TL_error *error2, int32_t networkType, int64_t responseTime, int64_t msgId) { + ConnectionsManager::getInstance(instanceNum).sendRequest(request2, [&](TLObject *response2, TL_error *error2, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { if (error2 == nullptr) { authorized = true; ConnectionsManager::getInstance(instanceNum).onDatacenterExportAuthorizationComplete(this); diff --git a/TMessagesProj/jni/tgnet/Defines.h b/TMessagesProj/jni/tgnet/Defines.h index 4949d183d2..213f1e4f9d 100644 --- a/TMessagesProj/jni/tgnet/Defines.h +++ b/TMessagesProj/jni/tgnet/Defines.h @@ -47,7 +47,7 @@ class NativeByteBuffer; class Handshake; class ConnectionSocket; -typedef std::function onCompleteFunc; +typedef std::function onCompleteFunc; typedef std::function onQuickAckFunc; typedef std::function onWriteToSocketFunc; typedef std::function onRequestClearFunc; diff --git a/TMessagesProj/jni/tgnet/Handshake.cpp b/TMessagesProj/jni/tgnet/Handshake.cpp index 93c798fffc..4d0ce7a0e6 100644 --- a/TMessagesProj/jni/tgnet/Handshake.cpp +++ b/TMessagesProj/jni/tgnet/Handshake.cpp @@ -873,7 +873,7 @@ void Handshake::processHandshakeResponse_serverDHParamsAnswer(TLObject *message, request->encrypted_message = currentDatacenter->createRequestsData(array, nullptr, connection, true); }; - authKeyPendingRequestId = ConnectionsManager::getInstance(currentDatacenter->instanceNum).sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + authKeyPendingRequestId = ConnectionsManager::getInstance(currentDatacenter->instanceNum).sendRequest(request, [&](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { authKeyPendingMessageId = 0; authKeyPendingRequestId = 0; if (response != nullptr && typeid(*response) == typeid(TL_boolTrue)) { @@ -989,7 +989,7 @@ void Handshake::loadCdnConfig(Datacenter *datacenter) { loadingCdnKeys = true; auto request = new TL_help_getCdnConfig(); - ConnectionsManager::getInstance(datacenter->instanceNum).sendRequest(request, [&, datacenter](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { + ConnectionsManager::getInstance(datacenter->instanceNum).sendRequest(request, [&, datacenter](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId) { if (response != nullptr) { auto config = (TL_cdnConfig *) response; size_t count = config->public_keys.size(); diff --git a/TMessagesProj/jni/tgnet/Request.cpp b/TMessagesProj/jni/tgnet/Request.cpp index 1d95236c89..d64dca32f9 100644 --- a/TMessagesProj/jni/tgnet/Request.cpp +++ b/TMessagesProj/jni/tgnet/Request.cpp @@ -52,10 +52,10 @@ void Request::clear(bool time) { } } -void Request::onComplete(TLObject *result, TL_error *error, int32_t networkType, int64_t responseTime, int64_t requestMsgId) { +void Request::onComplete(TLObject *result, TL_error *error, int32_t networkType, int64_t responseTime, int64_t requestMsgId, int32_t dcId) { if (onCompleteRequestCallback != nullptr && (result != nullptr || error != nullptr)) { completedSent = true; - onCompleteRequestCallback(result, error, networkType, responseTime, requestMsgId); + onCompleteRequestCallback(result, error, networkType, responseTime, requestMsgId, dcId); } } diff --git a/TMessagesProj/jni/tgnet/Request.h b/TMessagesProj/jni/tgnet/Request.h index 1c3f66a6ef..45287b8f8d 100644 --- a/TMessagesProj/jni/tgnet/Request.h +++ b/TMessagesProj/jni/tgnet/Request.h @@ -66,7 +66,7 @@ class Request { void addRespondMessageId(int64_t id); bool respondsToMessageId(int64_t id); void clear(bool time); - void onComplete(TLObject *result, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msg_id); + void onComplete(TLObject *result, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msg_id, int32_t dcId); void onQuickAck(); void onWriteToSocket(); bool isMediaRequest(); diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index d4c06411d5..a7f886268e 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -401,6 +401,14 @@ + + + + + + diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index 5c400cef32..fea126b2e8 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -446,3 +446,4 @@ iv_backgroundGray=-14737633 iv_navigationBackground=-16777216 table_background=177390847 table_border=436207615 +dialogCardShadow=1073741824 diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index 3ad321175a..9a90be13c5 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -471,3 +471,4 @@ iv_backgroundGray=-14737633 iv_navigationBackground=-16777216 table_background=177390847 table_border=436207615 +dialogCardShadow=1073741824 diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java index f909f67812..00b9c79473 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java @@ -16,12 +16,16 @@ package androidx.recyclerview.widget; +import android.text.TextUtils; import android.util.Log; import androidx.core.util.Pools; +import org.telegram.messenger.BuildVars; + import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; /** @@ -68,6 +72,29 @@ class AdapterHelper implements OpReorderer.Callback { private int mExistingUpdateTypes = 0; + private final ArrayList lastNotifies = BuildVars.DEBUG_VERSION ? new ArrayList() : null; + private void logNotify(String name) { + if (lastNotifies == null) return; + while (lastNotifies.size() > 5) lastNotifies.remove(0); + final StringBuilder sb = new StringBuilder(); + sb.append(new Date().toString()).append(" ").append(name).append("\n"); + final StackTraceElement[] trace = new Exception().getStackTrace(); + for (int i = 0, j = 0; i < trace.length && j < 5; ++i) { + final String traceElement = trace[i].toString(); + if (traceElement.startsWith("androidx.recyclerview.widget.") && j == 0) { + continue; + } + sb.append("\n").append(traceElement).append("\n"); + j++; + } + lastNotifies.add(sb.toString()); + } + + public String getLastNotifies() { + if (lastNotifies == null) return null; + return TextUtils.join("\n\n", lastNotifies); + } + AdapterHelper(Callback callback) { this(callback, false); } @@ -504,6 +531,9 @@ boolean onItemRangeChanged(int positionStart, int itemCount, Object payload) { if (itemCount < 1) { return false; } + if (BuildVars.DEBUG_VERSION) { + logNotify("onItemRangeChanged(" + positionStart + ", " + itemCount + ", " + payload + ")"); + } mPendingUpdates.add(obtainUpdateOp(UpdateOp.UPDATE, positionStart, itemCount, payload)); mExistingUpdateTypes |= UpdateOp.UPDATE; return mPendingUpdates.size() == 1; @@ -516,6 +546,9 @@ boolean onItemRangeInserted(int positionStart, int itemCount) { if (itemCount < 1) { return false; } + if (BuildVars.DEBUG_VERSION) { + logNotify("onItemRangeInserted(" + positionStart + ", " + itemCount + ")"); + } mPendingUpdates.add(obtainUpdateOp(UpdateOp.ADD, positionStart, itemCount, null)); mExistingUpdateTypes |= UpdateOp.ADD; return mPendingUpdates.size() == 1; @@ -528,6 +561,9 @@ boolean onItemRangeRemoved(int positionStart, int itemCount) { if (itemCount < 1) { return false; } + if (BuildVars.DEBUG_VERSION) { + logNotify("onItemRangeRemoved(" + positionStart + ", " + itemCount + ")"); + } mPendingUpdates.add(obtainUpdateOp(UpdateOp.REMOVE, positionStart, itemCount, null)); mExistingUpdateTypes |= UpdateOp.REMOVE; return mPendingUpdates.size() == 1; @@ -543,6 +579,9 @@ boolean onItemRangeMoved(int from, int to, int itemCount) { if (itemCount != 1) { throw new IllegalArgumentException("Moving more than 1 item is not supported yet"); } + if (BuildVars.DEBUG_VERSION) { + logNotify("onItemRangeMoved(" + from + ", " + to + ", " + itemCount + ")"); + } mPendingUpdates.add(obtainUpdateOp(UpdateOp.MOVE, from, to, null)); mExistingUpdateTypes |= UpdateOp.MOVE; return mPendingUpdates.size() == 1; diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java index 5aac333f08..06ac776bea 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java @@ -63,6 +63,11 @@ public class DefaultItemAnimator extends SimpleItemAnimator { ArrayList mChangeAnimations = new ArrayList<>(); protected boolean delayAnimations = true; + private long delayIncrement = 0; + + public void setDelayIncrement(long increment) { + this.delayIncrement = increment; + } protected static class MoveInfo { public RecyclerView.ViewHolder holder; @@ -121,6 +126,7 @@ public void runPendingAnimations() { for (RecyclerView.ViewHolder holder : mPendingRemovals) { animateRemoveImpl(holder); } + final long[] delay = new long[] { 0 }; mPendingRemovals.clear(); // Next, move stuff if (movesPending) { @@ -179,8 +185,10 @@ public void run() { Runnable adder = new Runnable() { @Override public void run() { - for (RecyclerView.ViewHolder holder : additions) { - animateAddImpl(holder); + for (int i = additions.size() - 1; i >= 0; --i) { +// for (int i = 0; i < additions.size(); ++i) { + final RecyclerView.ViewHolder holder = additions.get(i); + animateAddImpl(holder, delay[0] += delayIncrement); } additions.clear(); mAdditionsList.remove(additions); @@ -224,6 +232,10 @@ public void setDelayAnimations(boolean value) { } protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { + animateRemoveImpl(holder, 0); + } + + public void animateRemoveImpl(final RecyclerView.ViewHolder holder, long delay) { final View view = holder.itemView; final ViewPropertyAnimator animation = view.animate(); mRemoveAnimations.add(holder); @@ -233,7 +245,7 @@ protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { } animation .setDuration(getRemoveDuration()) - .setStartDelay(getRemoveDelay()) + .setStartDelay(getRemoveDelay() + delay) .setInterpolator(getRemoveInterpolator()) .alpha(0) .scaleX(1f - animateByScale(view)) @@ -280,6 +292,10 @@ public boolean animateAdd(final RecyclerView.ViewHolder holder) { } public void animateAddImpl(final RecyclerView.ViewHolder holder) { + animateAddImpl(holder, 0); + } + + public void animateAddImpl(final RecyclerView.ViewHolder holder, long delay) { final View view = holder.itemView; final ViewPropertyAnimator animation = view.animate(); mAddAnimations.add(holder); @@ -288,7 +304,7 @@ public void animateAddImpl(final RecyclerView.ViewHolder holder) { .scaleX(1f) .scaleY(1f) .setDuration(getAddDuration()) - .setStartDelay(getAddDelay()) + .setStartDelay(getAddDelay() + delay) .setInterpolator(getAddInterpolator()); if (Build.VERSION.SDK_INT >= 19) { animation.setUpdateListener(animation1 -> onAddAnimationUpdate(holder)); @@ -376,6 +392,10 @@ protected void afterAnimateChangeImpl(final RecyclerView.ViewHolder oldHolder, f } protected void animateMoveImpl(final RecyclerView.ViewHolder holder, MoveInfo moveInfo) { + animateMoveImpl(holder, moveInfo, 0); + } + + public void animateMoveImpl(final RecyclerView.ViewHolder holder, MoveInfo moveInfo, long delay) { int fromX = moveInfo.fromX; int fromY = moveInfo.fromY; int toX = moveInfo.toX; @@ -405,7 +425,7 @@ protected void animateMoveImpl(final RecyclerView.ViewHolder holder, MoveInfo mo beforeAnimateMoveImpl(holder); animation .setDuration(getMoveDuration()) - .setStartDelay(getMoveDelay()) + .setStartDelay(getMoveDelay() + delay) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animator) { @@ -470,6 +490,10 @@ public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.Vie } public void animateChangeImpl(final ChangeInfo changeInfo) { + animateChangeImpl(changeInfo, 0); + } + + public void animateChangeImpl(final ChangeInfo changeInfo, long delay) { final RecyclerView.ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; @@ -491,6 +515,7 @@ public void animateChangeImpl(final ChangeInfo changeInfo) { oldViewAnim.setUpdateListener(animation1 -> onChangeAnimationUpdate(changeInfo.oldHolder)); } oldViewAnim + .setStartDelay(delay) .setInterpolator(getChangeInterpolator()) .setListener(new AnimatorListenerAdapter() { @Override @@ -520,7 +545,7 @@ public void onAnimationEnd(Animator animator) { newViewAnimation .translationX(0).translationY(0) .setDuration(getChangeAddDuration()) - .setStartDelay(getChangeDelay() + (getChangeDuration() - getChangeAddDuration())) + .setStartDelay(getChangeDelay() + (getChangeDuration() - getChangeAddDuration()) + delay) .setInterpolator(getChangeInterpolator()) .alpha(1); if (animateByScale(newView) > 0) { diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java index 42ca8a991b..9266c70d2c 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java @@ -774,10 +774,16 @@ public RecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int * hitting an exception. */ String exceptionLabel() { - return " " + super.toString() - + ", adapter:" + mAdapter - + ", layout:" + mLayout - + ", context:" + getContext(); + final StringBuilder sb = new StringBuilder(); + sb.append(" ").append(super.toString()) + .append(", adapter:").append(mAdapter) + .append(", layout:").append(mLayout) + .append(", context:").append(getContext()); + final String lastNotifies = mAdapterHelper.getLastNotifies(); + if (lastNotifies != null) { + sb.append(", last notifies:\n").append(lastNotifies); + } + return sb.toString(); } /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index 16583004fc..98d269433d 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -634,7 +634,7 @@ private static boolean isAliasV29(android.media.MediaCodecInfo info) { * The result of {@link android.media.MediaCodecInfo#isHardwareAccelerated()} for API levels 29+, * or a best-effort approximation for lower levels. */ - private static boolean isHardwareAccelerated( + public static boolean isHardwareAccelerated( android.media.MediaCodecInfo codecInfo, String mimeType) { if (Util.SDK_INT >= 29) { return isHardwareAcceleratedV29(codecInfo); diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java index 9bdc2b9079..36f92739a0 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java @@ -427,7 +427,7 @@ private void maybeLoadInitData() throws IOException { initDataSource, initDataSpec, initSegmentEncrypted, - /* initializeTimestampAdjuster= */ false); + /* initializeTimestampAdjuster= */ true); nextLoadPosition = 0; initDataLoadRequired = false; } diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java index 9df0dd87fa..5294d43ac4 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java @@ -25,6 +25,8 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Log; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java index ce6243eda0..1e2c4a5bd3 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java @@ -19,6 +19,9 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import androidx.annotation.Nullable; + +import com.google.android.exoplayer2.util.Log; + import java.util.ArrayList; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java index 7e5dd4c302..5eaef23fba 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java @@ -319,7 +319,7 @@ public static String getStringForHttpMethod(@HttpMethod int httpMethod) { } /** A {@link Uri} from which data belonging to the resource can be read. */ - public final Uri uri; + public Uri uri; /** * The offset of the data located at {@link #uri} within the resource. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java index f5d7dbd24c..eaed29a0f7 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java @@ -53,7 +53,7 @@ public DefaultHttpDataSourceFactory(String userAgent) { */ public DefaultHttpDataSourceFactory(String userAgent, @Nullable TransferListener listener) { this(userAgent, listener, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, - DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, false); + DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true); } /** diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index de00100d04..647911b2ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -500,6 +500,17 @@ public static CharSequence highlightText(CharSequence str, String query, Theme.R return spannableStringBuilder; } + public static Activity getActivity() { + return getActivity(null); + } + + public static Activity getActivity(Context context) { + Activity activity = findActivity(context); + if (activity == null || activity.isFinishing()) activity = LaunchActivity.instance; + if (activity == null || activity.isFinishing()) activity = findActivity(ApplicationLoader.applicationContext); + return activity; + } + public static Activity findActivity(Context context) { if (context instanceof Activity) { return (Activity) context; @@ -533,7 +544,7 @@ public static SpannableStringBuilder replaceSingleTag(String str, int colorKey, index = startIndex; } SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str); - if (index >= 0) { + if (runnable != null && index >= 0) { if (type == REPLACING_TAG_TYPE_LINK_NBSP) { spannableStringBuilder.replace(index, index + len, AndroidUtilities.replaceMultipleCharSequence(" ", spannableStringBuilder.subSequence(index, index + len), " ")); } @@ -574,6 +585,43 @@ public void updateDrawState(TextPaint textPaint) { return spannableStringBuilder; } + public static SpannableStringBuilder makeClickable(String str, int type, Runnable runnable, Theme.ResourcesProvider resourcesProvider) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str); + if (type == REPLACING_TAG_TYPE_LINK || type == REPLACING_TAG_TYPE_LINK_NBSP || type == REPLACING_TAG_TYPE_LINKBOLD || type == REPLACING_TAG_TYPE_UNDERLINE) { + spannableStringBuilder.setSpan(new ClickableSpan() { + @Override + public void updateDrawState(@NonNull TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(type == REPLACING_TAG_TYPE_UNDERLINE); + if (type == REPLACING_TAG_TYPE_LINKBOLD) { + ds.setTypeface(AndroidUtilities.bold()); + } + } + @Override + public void onClick(@NonNull View view) { + if (runnable != null) { + runnable.run(); + } + } + }, 0, spannableStringBuilder.length(), 0); + } else { + spannableStringBuilder.setSpan(new CharacterStyle() { + @Override + public void updateDrawState(TextPaint textPaint) { + textPaint.setTypeface(AndroidUtilities.bold()); + int wasAlpha = textPaint.getAlpha(); + textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider)); + textPaint.setAlpha(wasAlpha); + } + }, 0, spannableStringBuilder.length(), 0); + } + return spannableStringBuilder; + } + + public static SpannableStringBuilder makeClickable(String str, Runnable runnable) { + return makeClickable(str, 0, runnable, null); + } + public static SpannableStringBuilder replaceMultipleTags(String str, Runnable ...runnables) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 1dadb79a7b..d2779cf106 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -50,6 +50,7 @@ import java.io.File; import java.util.ArrayList; +import java.util.Locale; public class ApplicationLoader extends Application { @@ -267,7 +268,23 @@ public void onCreate() { if (BuildVars.LOGS_ENABLED) { FileLog.d("app start time = " + (startTime = SystemClock.elapsedRealtime())); try { - FileLog.d("buildVersion = " + ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0).versionCode); + final PackageInfo info = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); + final String abi; + switch (info.versionCode % 10) { + case 1: + case 2: + abi = "store bundled " + Build.CPU_ABI + " " + Build.CPU_ABI2; + break; + default: + case 9: + if (ApplicationLoader.isStandaloneBuild()) { + abi = "direct " + Build.CPU_ABI + " " + Build.CPU_ABI2; + } else { + abi = "universal " + Build.CPU_ABI + " " + Build.CPU_ABI2; + } + break; + } + FileLog.d("buildVersion = " + String.format(Locale.US, "v%s (%d[%d]) %s", info.versionName, info.versionCode / 10, info.versionCode % 10, abi)); } catch (Exception e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index ea16016083..ee25da73d1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -43,6 +43,11 @@ public class BuildVars { if (ApplicationLoader.applicationContext != null) { SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE); LOGS_ENABLED = DEBUG_VERSION || sharedPreferences.getBoolean("logsEnabled", DEBUG_VERSION); + if (LOGS_ENABLED) { + Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> { + FileLog.fatal(exception, true); + }); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index 637d77d872..58f130c00b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -1801,6 +1801,15 @@ public static boolean isChannelAndNotMegaGroup(TLRPC.Chat chat) { return isChannel(chat) && !isMegagroup(chat); } + public static boolean isDiscussionGroup(int currentAccount, long chatId) { + final MessagesController messagesController = MessagesController.getInstance(currentAccount); + return isDiscussionGroup(messagesController.getChat(chatId), messagesController.getChatFull(chatId)); + } + + public static boolean isDiscussionGroup(TLRPC.Chat chat, TLRPC.ChatFull chatFull) { + return isMegagroup(chat) && chatFull != null && chatFull.linked_chat_id != 0; + } + public static boolean isBoostSupported(TLRPC.Chat chat) { return isChannelAndNotMegaGroup(chat) || isMegagroup(chat); } @@ -1906,6 +1915,9 @@ public static boolean canSendPolls(TLRPC.Chat chat) { } public static boolean canSendMessages(TLRPC.Chat chat) { + if (isNotInChat(chat) && chat != null && chat.join_to_send) { + return false; + } if (isIgnoredChatRestrictionsForBoosters(chat)) { return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/CopyCodeReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/CopyCodeReceiver.java new file mode 100644 index 0000000000..5bcf11eaa9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/CopyCodeReceiver.java @@ -0,0 +1,15 @@ +package org.telegram.messenger; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class CopyCodeReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + String text = intent.getStringExtra("text"); + AndroidUtilities.addToClipboard(text); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 176f3a61bb..d53f437793 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1522,6 +1522,19 @@ public static int migrate(MessagesStorage messagesStorage, int version) throws E version = 156; } + if (version == 156 || version == 157) { + database.executeFast("CREATE TABLE star_gifts2(id INTEGER PRIMARY KEY, data BLOB, hash INTEGER, time INTEGER);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 158").stepThis().dispose(); + version = 158; + } + + if (version == 158) { + database.executeFast("DELETE FROM star_gifts2").stepThis().dispose(); + database.executeFast("ALTER TABLE star_gifts2 ADD COLUMN pos INTEGER default 0;").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 159").stepThis().dispose(); + version = 159; + } + return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java index f8f64638ea..3cb7a749b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java @@ -169,6 +169,9 @@ public static String getPublicUsername(TLObject dialog) { } public static long getEmojiStatusDocumentId(TLRPC.EmojiStatus emojiStatus) { + if (MessagesController.getInstance(UserConfig.selectedAccount).premiumFeaturesBlocked()) { + return 0; + } if (emojiStatus instanceof TLRPC.TL_emojiStatus) { return ((TLRPC.TL_emojiStatus) emojiStatus).document_id; } else if (emojiStatus instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) emojiStatus).until > (int) (System.currentTimeMillis() / 1000)) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FactCheckController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FactCheckController.java index eb0b35afed..ed27c10688 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FactCheckController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FactCheckController.java @@ -397,14 +397,14 @@ protected void extendActionMode(ActionMode actionMode, Menu menu) { menu.removeItem(android.R.id.shareText); } int order = 6; - SpannableStringBuilder stringBuilder = new SpannableStringBuilder(getString("Bold", R.string.Bold)); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(getString(R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, order++, stringBuilder); - stringBuilder = new SpannableStringBuilder(getString("Italic", R.string.Italic)); - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder = new SpannableStringBuilder(getString(R.string.Italic)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM_ITALIC)), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_italic, order++, stringBuilder); - menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, getString("CreateLink", R.string.CreateLink)); - menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, getString("Regular", R.string.Regular)); + menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, getString(R.string.CreateLink)); + menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, getString(R.string.Regular)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 567fec8d42..8aab6ea5fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -8,8 +8,6 @@ package org.telegram.messenger; -import android.util.Log; - import org.telegram.messenger.utils.ImmutableByteArrayOutputStream; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; @@ -51,7 +49,7 @@ public class FileLoadOperation { public volatile boolean caughtPremiumFloodWait; public void setStream(FileLoadOperationStream stream, boolean streamPriority, long streamOffset) { - FileLog.e("FileLoadOperation " + getFileName() + " setStream(" + stream + ")"); +// FileLog.e("FileLoadOperation " + getFileName() + " setStream(" + stream + ")"); this.stream = stream; this.streamOffset = streamOffset; this.streamPriority = streamPriority; @@ -240,6 +238,7 @@ private PreloadRange(long o, long l) { private byte[] cdnCheckBytes; private boolean requestingCdnOffsets; + public final ArrayList uiRequestTokens = new ArrayList<>(); public ArrayList requestInfos; private ArrayList cancelledRequestInfos; private ArrayList delayedRequestInfos; @@ -249,6 +248,7 @@ private PreloadRange(long o, long l) { private File cacheFileFinal; private File cacheIvTemp; private File cacheFileParts; + private boolean cacheFileFinalReady; private String ext; private RandomAccessFile fileOutputStream; @@ -686,7 +686,7 @@ protected File getCurrentFile() { } protected File getCurrentFileFast() { - if (state == stateFinished && !preloadFinished) { + if (state == stateFinished && !preloadFinished && cacheFileFinalReady) { return cacheFileFinal; } else { return cacheFileTemp; @@ -836,7 +836,9 @@ public boolean start(final FileLoadOperationStream stream, final long streamOffs if (streamPriority) { long offset = (streamOffset / (long) currentDownloadChunkSize) * (long) currentDownloadChunkSize; if (priorityRequestInfo != null && priorityRequestInfo.offset != offset) { + final int requestToken = priorityRequestInfo.requestToken; requestInfos.remove(priorityRequestInfo); + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.remove((Integer) requestToken)); requestedBytesCount -= currentDownloadChunkSize; removePart(notRequestedBytesRanges, priorityRequestInfo.offset, priorityRequestInfo.offset + currentDownloadChunkSize); if (priorityRequestInfo.requestToken != 0) { @@ -978,7 +980,7 @@ public boolean start(final FileLoadOperationStream stream, final long streamOffs cacheFileFinal = new File(storePath, fileNameFinal); } } - boolean finalFileExist = cacheFileFinal.exists(); + boolean finalFileExist = cacheFileFinalReady = cacheFileFinal.exists(); if (finalFileExist && (parentObject instanceof TLRPC.TL_theme || (totalBytesCount != 0 && !ungzip && totalBytesCount != cacheFileFinal.length())) && !delegate.isLocallyCreatedFile(cacheFileFinal.toString())) { if (BuildVars.LOGS_ENABLED) { FileLog.d("debug_loading: delete existing file cause file size mismatch " + cacheFileFinal.getName() + " totalSize=" + totalBytesCount + " existingFileSize=" + cacheFileFinal.length()); @@ -1626,7 +1628,9 @@ private void onFinishLoadingFile(final boolean increment, int finishCode, boolea return; } cacheFileFinal = cacheFileTempLocal; + cacheFileFinalReady = false; } else { + cacheFileFinalReady = true; if (pathSaveData != null && cacheFileFinal.exists()) { delegate.saveFilePath(pathSaveData, cacheFileFinal); } @@ -1779,7 +1783,9 @@ protected boolean processRequestResult(RequestInfo requestInfo, TLRPC.TL_error e } return false; } + final int requestToken = requestInfo.requestToken; requestInfos.remove(requestInfo); + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.remove((Integer) requestToken)); if (error == null) { try { if (notLoadedBytesRanges == null && downloadedBytes != requestInfo.offset) { @@ -2149,6 +2155,7 @@ private void clearOperation(RequestInfo currentInfo, boolean preloadChanged, boo } } requestInfos.clear(); + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.clear()); for (int a = 0; a < delayedRequestInfos.size(); a++) { RequestInfo info = delayedRequestInfos.get(a); if (isPreloadVideoOperation) { @@ -2406,7 +2413,7 @@ protected void startDownloadRequest(int useConnectionType) { } flags |= ConnectionsManager.RequestFlagListenAfterCancel; int datacenterId = isCdn ? cdnDatacenterId : this.datacenterId; - requestInfo.requestToken = ConnectionsManager.getInstance(currentAccount).sendRequestSync(request, (response, error) -> { + final int requestToken = requestInfo.requestToken = ConnectionsManager.getInstance(currentAccount).sendRequestSync(request, (response, error) -> { if (requestInfo.cancelled) { FileLog.e("received chunk but definitely cancelled offset=" + requestInfo.offset + " size=" + requestInfo.chunkSize + " token=" + requestInfo.requestToken); return; @@ -2573,6 +2580,7 @@ protected void startDownloadRequest(int useConnectionType) { if (BuildVars.LOGS_ENABLED) { FileLog.d("debug_loading: " + cacheFileFinal.getName() + " dc=" + datacenterId + " send reqId " + requestInfo.requestToken + " offset=" + requestInfo.offset + " conType=" + connectionType + " priority=" + priority); } + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.add(requestToken)); requestsCount++; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 608bbaf45e..4cd8c551e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -682,11 +682,8 @@ public void cancelLoadAllFiles() { public FileUploadOperation findUploadOperationByRequestToken(final int requestToken) { for (FileUploadOperation operation : uploadOperationPaths.values()) { - if (operation == null) continue; - for (int i = 0; i < operation.requestTokens.size(); ++i) { - if (operation.requestTokens.valueAt(i) == requestToken) { - return operation; - } + if (operation != null && operation.uiRequestTokens.contains(requestToken)) { + return operation; } } return null; @@ -704,11 +701,8 @@ public boolean checkUploadCaughtPremiumFloodWait(final String filename) { public FileLoadOperation findLoadOperationByRequestToken(final int requestToken) { for (FileLoadOperation operation : loadOperationPaths.values()) { - if (operation == null || operation.requestInfos == null) continue; - for (FileLoadOperation.RequestInfo requestInfo : operation.requestInfos) { - if (requestInfo != null && requestInfo.requestToken == requestToken) { - return operation; - } + if (operation != null && operation.uiRequestTokens.contains(requestToken)) { + return operation; } } return null; @@ -821,7 +815,7 @@ private FileLoadOperation loadFileInternal(final TLRPC.Document document, final if (priorityChanged) { operation.getQueue().checkLoadingOperations(); } - FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " preloadFinish " + operation.isPreloadFinished() + " priority=" + operation.getPriority()); +// FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " preloadFinish " + operation.isPreloadFinished() + " priority=" + operation.getPriority()); return operation; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index e9b95dbc61..8323efd85b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -83,7 +83,7 @@ public FileLog() { private static HashSet excludeRequests; public static void dumpResponseAndRequest(int account, TLObject request, TLObject response, TLRPC.TL_error error, long requestMsgId, long startRequestTimeInMillis, int requestToken) { - if (false && (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || request == null)) { + if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || request == null) { return; } String requestSimpleName = request.getClass().getSimpleName(); @@ -127,7 +127,7 @@ public static void dumpResponseAndRequest(int account, TLObject request, TLObjec } public static void dumpUnparsedMessage(TLObject message, long messageId, int account) { - if (false && (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null)) { + if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null) { return; } try { @@ -330,6 +330,10 @@ public static void e(final String message, final Throwable exception) { try { getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + message + "\n"); getInstance().streamWriter.write(exception.toString()); + StackTraceElement[] stack = exception.getStackTrace(); + for (int a = 0; a < stack.length; a++) { + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: \tat " + stack[a] + "\n"); + } getInstance().streamWriter.flush(); } catch (Exception e) { e.printStackTrace(); @@ -386,12 +390,19 @@ public static void e(final Throwable e, boolean logToAppCenter) { e.printStackTrace(); if (getInstance().streamWriter != null) { getInstance().logQueue.postRunnable(() -> { - try { getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + e + "\n"); StackTraceElement[] stack = e.getStackTrace(); for (int a = 0; a < stack.length; a++) { - getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + stack[a] + "\n"); + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: \tat " + stack[a] + "\n"); + } + Throwable cause = e.getCause(); + if (cause != null) { + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: Caused by " + cause + "\n"); + stack = cause.getStackTrace(); + for (int a = 0; a < stack.length; a++) { + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: \tat " + stack[a] + "\n"); + } } getInstance().streamWriter.flush(); } catch (Exception e1) { @@ -411,7 +422,7 @@ public static void fatal(final Throwable e, boolean logToAppCenter) { if (!BuildVars.LOGS_ENABLED) { return; } - if (BuildVars.DEBUG_VERSION && needSent(e) && logToAppCenter) { + if (logToAppCenter && BuildVars.DEBUG_VERSION && needSent(e)) { AndroidUtilities.appCenterLog(e); } ensureInitied(); @@ -419,10 +430,18 @@ public static void fatal(final Throwable e, boolean logToAppCenter) { if (getInstance().streamWriter != null) { getInstance().logQueue.postRunnable(() -> { try { - getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + e + "\n"); + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " FATAL/tmessages: " + e + "\n"); StackTraceElement[] stack = e.getStackTrace(); for (int a = 0; a < stack.length; a++) { - getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + stack[a] + "\n"); + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " FATAL/tmessages: \tat " + stack[a] + "\n"); + } + Throwable cause = e.getCause(); + if (cause != null) { + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: Caused by " + cause + "\n"); + stack = cause.getStackTrace(); + for (int a = 0; a < stack.length; a++) { + getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: \tat " + stack[a] + "\n"); + } } getInstance().streamWriter.flush(); } catch (Exception e1) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 01a98db850..d1f1df2f75 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -951,7 +951,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject if (response instanceof StoriesController.BotPreview) { StoriesController.BotPreview newStoryItem = (StoriesController.BotPreview) response; if (newStoryItem.media.document != null) { - result = getFileReference(newStoryItem.media.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(newStoryItem.media.document, newStoryItem.media.alt_documents, requester.location, needReplacement, locationReplacement); } else if (newStoryItem.media.photo != null) { result = getFileReference(newStoryItem.media.photo, requester.location, needReplacement, locationReplacement); } @@ -968,9 +968,9 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject TLRPC.MessageMedia media = ((TLRPC.TL_messageExtendedMedia) extendedMedia).media; if (media != null) { if (media.document != null) { - result = getFileReference(media.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(media.document, media.alt_documents, requester.location, needReplacement, locationReplacement); } else if (media.game != null) { - result = getFileReference(media.game.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(media.game.document, null, requester.location, needReplacement, locationReplacement); if (result == null) { result = getFileReference(media.game.photo, requester.location, needReplacement, locationReplacement); } @@ -987,9 +987,9 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } } else if (message.media != null) { if (message.media.document != null) { - result = getFileReference(message.media.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(message.media.document, message.media.alt_documents, requester.location, needReplacement, locationReplacement); } else if (message.media.game != null) { - result = getFileReference(message.media.game.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(message.media.game.document, null, requester.location, needReplacement, locationReplacement); if (result == null) { result = getFileReference(message.media.game.photo, requester.location, needReplacement, locationReplacement); } @@ -1022,7 +1022,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_help_premiumPromo) { TLRPC.TL_help_premiumPromo premiumPromo = (TLRPC.TL_help_premiumPromo) response; for (TLRPC.Document document : premiumPromo.videos) { - result = getFileReference(document, requester.location, needReplacement, locationReplacement); + result = getFileReference(document, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1032,31 +1032,31 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject getMediaDataController().processLoadedReactions(availableReactions.reactions, availableReactions.hash, (int) (System.currentTimeMillis() / 1000), false); for (TLRPC.TL_availableReaction reaction : availableReactions.reactions) { - result = getFileReference(reaction.static_icon, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.static_icon, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } - result = getFileReference(reaction.appear_animation, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.appear_animation, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } - result = getFileReference(reaction.select_animation, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.select_animation, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } - result = getFileReference(reaction.activate_animation, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.activate_animation, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } - result = getFileReference(reaction.effect_animation, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.effect_animation, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } - result = getFileReference(reaction.around_animation, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.around_animation, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } - result = getFileReference(reaction.center_icon, requester.location, needReplacement, locationReplacement); + result = getFileReference(reaction.center_icon, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1070,7 +1070,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject if (botInfo != null) { getMessagesStorage().updateUserInfo(userFull, true); - result = getFileReference(botInfo.description_document, requester.location, needReplacement, locationReplacement); + result = getFileReference(botInfo.description_document, null, requester.location, needReplacement, locationReplacement); if (result != null) { continue; @@ -1081,7 +1081,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_attachMenuBotsBot) { TLRPC.TL_attachMenuBot bot = ((TLRPC.TL_attachMenuBotsBot) response).bot; for (TLRPC.TL_attachMenuBotIcon icon : bot.icons) { - result = getFileReference(icon.icon, requester.location, needReplacement, locationReplacement); + result = getFileReference(icon.icon, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1128,10 +1128,10 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject FileLog.e(e); } if (result == null) { - result = getFileReference(appUpdate.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(appUpdate.document, null, requester.location, needReplacement, locationReplacement); } if (result == null) { - result = getFileReference(appUpdate.sticker, requester.location, needReplacement, locationReplacement); + result = getFileReference(appUpdate.sticker, null, requester.location, needReplacement, locationReplacement); } } else if (response instanceof TLRPC.TL_messages_webPage) { TLRPC.TL_messages_webPage res = (TLRPC.TL_messages_webPage) response; @@ -1143,7 +1143,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_account_wallPapers) { TLRPC.TL_account_wallPapers accountWallPapers = (TLRPC.TL_account_wallPapers) response; for (int i = 0, size10 = accountWallPapers.wallpapers.size(); i < size10; i++) { - result = getFileReference(((TLRPC.WallPaper) accountWallPapers.wallpapers.get(i)).document, requester.location, needReplacement, locationReplacement); + result = getFileReference(((TLRPC.WallPaper) accountWallPapers.wallpapers.get(i)).document, null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1153,7 +1153,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } } else if (response instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response; - result = getFileReference(wallPaper.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(wallPaper.document, null, requester.location, needReplacement, locationReplacement); if (result != null && cache) { ArrayList wallpapers = new ArrayList<>(); wallpapers.add(wallPaper); @@ -1161,7 +1161,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } } else if (response instanceof TLRPC.TL_theme) { TLRPC.TL_theme theme = (TLRPC.TL_theme) response; - result = getFileReference(theme.document, requester.location, needReplacement, locationReplacement); + result = getFileReference(theme.document, null, requester.location, needReplacement, locationReplacement); if (result != null && cache) { AndroidUtilities.runOnUIThread(() -> Theme.setThemeFileReference(theme)); } @@ -1214,7 +1214,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_messages_savedGifs) { TLRPC.TL_messages_savedGifs savedGifs = (TLRPC.TL_messages_savedGifs) response; for (int b = 0, size2 = savedGifs.gifs.size(); b < size2; b++) { - result = getFileReference(savedGifs.gifs.get(b), requester.location, needReplacement, locationReplacement); + result = getFileReference(savedGifs.gifs.get(b), null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1226,7 +1226,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject TLRPC.TL_messages_stickerSet stickerSet = (TLRPC.TL_messages_stickerSet) response; if (result == null) { for (int b = 0, size2 = stickerSet.documents.size(); b < size2; b++) { - result = getFileReference(stickerSet.documents.get(b), requester.location, needReplacement, locationReplacement); + result = getFileReference(stickerSet.documents.get(b), null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1238,7 +1238,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_messages_recentStickers) { TLRPC.TL_messages_recentStickers recentStickers = (TLRPC.TL_messages_recentStickers) response; for (int b = 0, size2 = recentStickers.stickers.size(); b < size2; b++) { - result = getFileReference(recentStickers.stickers.get(b), requester.location, needReplacement, locationReplacement); + result = getFileReference(recentStickers.stickers.get(b), null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1249,7 +1249,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_messages_favedStickers) { TLRPC.TL_messages_favedStickers favedStickers = (TLRPC.TL_messages_favedStickers) response; for (int b = 0, size2 = favedStickers.stickers.size(); b < size2; b++) { - result = getFileReference(favedStickers.stickers.get(b), requester.location, needReplacement, locationReplacement); + result = getFileReference(favedStickers.stickers.get(b), null, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -1276,10 +1276,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject result = getFileReference(storyItem.media.photo, requester.location, needReplacement, locationReplacement); } if (result == null && storyItem.media.document != null) { - result = getFileReference(storyItem.media.document, requester.location, needReplacement, locationReplacement); - } - if (result == null && storyItem.media.alt_document != null) { - result = getFileReference(storyItem.media.alt_document, requester.location, needReplacement, locationReplacement); + result = getFileReference(storyItem.media.document, storyItem.media.alt_documents, requester.location, needReplacement, locationReplacement); } } } @@ -1370,7 +1367,7 @@ private void putReponseToCache(String key, TLObject response) { } } - private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { + private byte[] getFileReference(TLRPC.Document document, ArrayList alt_documents, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { if (document == null || location == null) { return null; } @@ -1397,6 +1394,14 @@ private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation } } } + if (alt_documents != null) { + byte[] result = null; + for (int i = 0; i < alt_documents.size(); ++i) { + if ((result = getFileReference(alt_documents.get(i), null, location, needReplacement, replacement)) != null) { + return result; + } + } + } return null; } @@ -1525,7 +1530,7 @@ private byte[] getFileReference(TLRPC.FileLocation fileLocation, TLRPC.InputFile } private byte[] getFileReference(TLRPC.WebPage webpage, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { - byte[] result = getFileReference(webpage.document, location, needReplacement, replacement); + byte[] result = getFileReference(webpage.document, null, location, needReplacement, replacement); if (result != null) { return result; } @@ -1541,7 +1546,7 @@ private byte[] getFileReference(TLRPC.WebPage webpage, TLRPC.InputFileLocation l } TLRPC.TL_webPageAttributeTheme attribute = (TLRPC.TL_webPageAttributeTheme) attribute_; for (int b = 0, size2 = attribute.documents.size(); b < size2; b++) { - result = getFileReference(attribute.documents.get(b), location, needReplacement, replacement); + result = getFileReference(attribute.documents.get(b), null, location, needReplacement, replacement); if (result != null) { return result; } @@ -1550,7 +1555,7 @@ private byte[] getFileReference(TLRPC.WebPage webpage, TLRPC.InputFileLocation l } if (webpage.cached_page != null) { for (int b = 0, size2 = webpage.cached_page.documents.size(); b < size2; b++) { - result = getFileReference(webpage.cached_page.documents.get(b), location, needReplacement, replacement); + result = getFileReference(webpage.cached_page.documents.get(b), null, location, needReplacement, replacement); if (result != null) { return result; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java index 683cbdc237..8863ea054b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java @@ -38,6 +38,8 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO private Uri uri; private long bytesRemaining; + private long bytesTransferred; + private long requestedLength; private boolean opened; private long currentOffset; private CountDownLatch countDownLatch; @@ -94,10 +96,13 @@ public long open(DataSpec dataSpec) throws IOException { document.attributes.add(new TLRPC.TL_documentAttributeAudio()); } allStreams.put(document.id, this); - loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, null, parentObject, currentOffset = dataSpec.position, false, getCurrentPriority()); - bytesRemaining = dataSpec.length == C.LENGTH_UNSET ? document.size - dataSpec.position : dataSpec.length; - if (bytesRemaining < 0) { - throw new EOFException(); + currentOffset = dataSpec.position; + requestedLength = dataSpec.length; + loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, null, parentObject, currentOffset, false, getCurrentPriority()); + bytesTransferred = 0; + bytesRemaining = document.size - dataSpec.position; + if (requestedLength != C.LENGTH_UNSET) { + bytesRemaining = Math.min(bytesRemaining, requestedLength - bytesTransferred); } opened = true; transferStarted(dataSpec); @@ -109,6 +114,9 @@ public long open(DataSpec dataSpec) throws IOException { file.seek(currentOffset); if (loadOperation.isFinished()) { bytesRemaining = currentFile.length() - currentOffset; + if (requestedLength != C.LENGTH_UNSET) { + bytesRemaining = Math.min(bytesRemaining, requestedLength - bytesTransferred); + } } } catch (Throwable e) { } @@ -178,6 +186,9 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { file.seek(currentOffset); if (loadOperation.isFinished()) { bytesRemaining = currentFile.length() - currentOffset; + if (requestedLength != C.LENGTH_UNSET) { + bytesRemaining = Math.min(bytesRemaining, requestedLength - bytesTransferred); + } } } catch (Throwable e) { @@ -195,6 +206,7 @@ public int read(byte[] buffer, int offset, int readLength) throws IOException { if (bytesRead > 0) { currentOffset += bytesRead; bytesRemaining -= bytesRead; + bytesTransferred += bytesRead; bytesTransferred(bytesRead); } } catch (Exception e) { @@ -239,9 +251,10 @@ public void close() { @Override public void newDataAvailable() { // FileLog.e("FileStreamLoadOperation " + document.id + " newDataAvailable me=" + this); - if (countDownLatch != null) { - countDownLatch.countDown(); - countDownLatch = null; + CountDownLatch latch = countDownLatch; + countDownLatch = null; + if (latch != null) { + latch.countDown(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index 69a07c03ad..b2ebccd728 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -54,6 +54,7 @@ private static class UploadCachedResult { private byte[] readBuffer; private FileUploadOperationDelegate delegate; public final SparseIntArray requestTokens = new SparseIntArray(); + public final ArrayList uiRequestTokens = new ArrayList<>(); private int currentPartNum; private long currentFileId; private long totalFileSize; @@ -162,6 +163,7 @@ protected void onNetworkChanged(final boolean slow) { } } }); + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.clear()); } public void cancel() { @@ -570,6 +572,7 @@ private void startUploadRequest() { freeRequestIvs.add(currentRequestIv); } requestTokens.delete(requestNumFinal); + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.remove((Integer) requestToken[0])); if (response instanceof TLRPC.TL_boolTrue) { if (state != 1) { return; @@ -676,5 +679,6 @@ private void startUploadRequest() { FileLog.d("debug_uploading: " + " send reqId " + requestToken[0] + " " + uploadingFilePath + " file_part=" + currentRequestPartNum + " isBig=" + isBigFile + " file_id=" + currentFileId); } requestTokens.put(requestNumFinal, requestToken[0]); + AndroidUtilities.runOnUIThread(() -> uiRequestTokens.add(requestToken[0])); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 855e04fd68..ce5c6b1b1e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -2047,12 +2047,10 @@ public void setManualAlphaAnimator(boolean value) { manualAlphaAnimator = value; } - @Keep public float getCurrentAlpha() { return currentAlpha; } - @Keep public void setCurrentAlpha(float value) { currentAlpha = value; } @@ -2602,6 +2600,10 @@ public void setAutoRepeat(int value) { } } + public int getAutoRepeat() { + return autoRepeat; + } + public void setAutoRepeatCount(int count) { autoRepeatCount = count; if (getLottieAnimation() != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index fb9da6eb02..bfffef1cb7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -89,6 +89,7 @@ import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; +import org.telegram.ui.Stories.DarkThemeResourceProvider; import java.io.File; import java.io.FileDescriptor; @@ -727,12 +728,14 @@ public static class VideoConvertMessage { public VideoEditedInfo videoEditedInfo; public int currentAccount; public boolean foreground; + public boolean foregroundConversion; - public VideoConvertMessage(MessageObject object, VideoEditedInfo info, boolean foreground) { + public VideoConvertMessage(MessageObject object, VideoEditedInfo info, boolean foreground, boolean conversion) { messageObject = object; currentAccount = messageObject.currentAccount; videoEditedInfo = info; this.foreground = foreground; + this.foregroundConversion = conversion; } } @@ -4372,11 +4375,14 @@ public MediaLoader(Context context, AccountInstance accountInstance, ArrayList cancelled = true); + progressDialog.setCancelDialog(true); + progressDialog.setOnCancelListener(d -> { + cancelled = true; + }); } public void start() { @@ -4392,7 +4398,12 @@ public void start() { for (int b = 0, N = messageObjects.size(); b < N; b++) { MessageObject message = messageObjects.get(b); String path = message.messageOwner.attachPath; - String name = message.getDocumentName(); + TLRPC.Document document = message.getDocument(); + if (message.qualityToSave != null) { + document = message.qualityToSave; + path = null; + } + String name = FileLoader.getDocumentFileName(document); if (path != null && path.length() > 0) { File temp = new File(path); if (!temp.exists()) { @@ -4400,18 +4411,21 @@ public void start() { } } if (TextUtils.isEmpty(path)) { -// path = null; -// TLRPC.Document document = message.getDocument(); -// if (!TextUtils.isEmpty(FileLoader.getDocumentFileName(document)) && !(message.messageOwner instanceof TLRPC.TL_message_secret) && FileLoader.canSaveAsFile(message)) { -// String filename = FileLoader.getDocumentFileName(document); -// File newDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_FILES); -// if (newDir != null) { -// path = new File(newDir, filename).getAbsolutePath(); -// } -// } -// if (path == null) { - path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString(); -// } + final FileLoader fileLoader = FileLoader.getInstance(currentAccount.getCurrentAccount()); + final TLRPC.MessageMedia media = MessageObject.getMedia(message); + File file = null; + if (message.qualityToSave != null) { + file = fileLoader.getPathToAttach(message.qualityToSave, null, false, true); + } else { + file = fileLoader.getPathToMessage(message.messageOwner, true); + if (media instanceof TLRPC.TL_messageMediaDocument) { + final TLRPC.TL_messageMediaDocument mediaDocument = (TLRPC.TL_messageMediaDocument) media; + if (!mediaDocument.alt_documents.isEmpty()) { + file = fileLoader.getPathToAttach(mediaDocument.alt_documents.get(0), null, false, true); + } + } + } + path = file.toString(); } File sourceFile = new File(path); if (!sourceFile.exists()) { @@ -4441,7 +4455,11 @@ public void start() { dir.mkdir(); for (int b = 0, N = messageObjects.size(); b < N; b++) { MessageObject message = messageObjects.get(b); - String name = message.getDocumentName(); + TLRPC.Document document = message.getDocument(); + if (message.qualityToSave != null) { + document = message.qualityToSave; + } + String name = FileLoader.getDocumentFileName(document); File destFile = new File(dir, name); if (destFile.exists()) { int idx = name.lastIndexOf('.'); @@ -4462,16 +4480,24 @@ public void start() { destFile.createNewFile(); } String path = message.messageOwner.attachPath; + if (message.qualityToSave != null) { + path = null; + } if (path != null && path.length() > 0) { File temp = new File(path); if (!temp.exists()) { path = null; } } - if (path == null || path.length() == 0) { - path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString(); + File sourceFile; + if (message.qualityToSave != null) { + sourceFile = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToAttach(message.qualityToSave, null, false, true); + } else { + if (path == null || path.length() == 0) { + path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString(); + } + sourceFile = new File(path); } - File sourceFile = new File(path); if (!sourceFile.exists()) { waitingForFile = new CountDownLatch(1); addMessageToLoad(message); @@ -4517,6 +4543,9 @@ private void checkIfFinished() { private void addMessageToLoad(MessageObject messageObject) { AndroidUtilities.runOnUIThread(() -> { TLRPC.Document document = messageObject.getDocument(); + if (messageObject.qualityToSave != null) { + document = messageObject.qualityToSave; + } if (document == null) { return; } @@ -5364,10 +5393,10 @@ private static void broadcastNewPhotos(final int guid, final ArrayList= 60 * 60) { + if (!isLoadingPremiumPromo && (premiumPromo == null || Math.abs(System.currentTimeMillis() / 1000 - premiumPromoUpdateDate) >= 60 * 60)) { loadPremiumPromo(true); } } @@ -654,9 +654,7 @@ public void loadPremiumPromo(boolean cache) { c.dispose(); } } - if (premiumPromo != null) { - processLoadedPremiumPromo(premiumPromo, date, true); - } + processLoadedPremiumPromo(premiumPromo, date, true); }); } else { TLRPC.TL_help_getPremiumPromo req = new TLRPC.TL_help_getPremiumPromo(); @@ -671,15 +669,24 @@ public void loadPremiumPromo(boolean cache) { } public void processLoadedPremiumPromo(TLRPC.TL_help_premiumPromo premiumPromo, int date, boolean cache) { - this.premiumPromo = premiumPromo; - premiumPromoUpdateDate = date; - getMessagesController().putUsers(premiumPromo.users, cache); - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.premiumPromoUpdated)); + if (premiumPromo != null) { + this.premiumPromo = premiumPromo; + premiumPromoUpdateDate = date; + getMessagesController().putUsers(premiumPromo.users, cache); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.premiumPromoUpdated)); + } if (!cache) { - putPremiumPromoToCache(premiumPromo, date); - } else if (Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60 * 24 || BuildVars.DEBUG_PRIVATE_VERSION) { - loadPremiumPromo(false); + if (premiumPromo != null) { + putPremiumPromoToCache(premiumPromo, date); + } + isLoadingPremiumPromo = false; + } else { + if (premiumPromo == null || Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60 * 24) { + loadPremiumPromo(false); + } else { + isLoadingPremiumPromo = false; + } } } @@ -793,7 +800,7 @@ public void processLoadedReactions(List reactions, i isLoadingReactions = false; if (!cache) { putReactionsToCache(reactions, hash, date); - } else if (Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60) { + } else if (Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60 || true) { loadReactions(false, hash); } } @@ -841,7 +848,7 @@ private void putReactionsToCache(List reactions, int getMessagesStorage().getDatabase().executeFast("DELETE FROM reactions").stepThis().dispose(); SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO reactions VALUES(?, ?, ?)"); state.requery(); - int size = 4; // Integer.BYTES + int size = 4; for (int a = 0; a < reactionsFinal.size(); a++) { size += reactionsFinal.get(a).getObjectSize(); } @@ -8778,8 +8785,10 @@ public void fillWithAnimatedEmoji(ArrayList result, Integer maxAn String emoticon = MessageObject.findAnimatedEmojiEmoticon(document, null); if (document != null && emoticon != null && emoticon.contains(emoji) && - (isPremium || MessageObject.isFreeEmoji(document)) + (isPremium || MessageObject.isFreeEmoji(document)) && + !foundEmojis.contains(document.id) ) { + foundEmojis.add(document.id); animatedEmoji.add(document); } } catch (Exception ignore) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 45b206a927..d5dccd3912 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -36,7 +36,6 @@ import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.Base64; -import android.util.Log; import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; @@ -75,6 +74,7 @@ import org.telegram.ui.Components.URLSpanNoUnderlineBold; import org.telegram.ui.Components.URLSpanReplacement; import org.telegram.ui.Components.URLSpanUserMention; +import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.PeerColorActivity; import org.telegram.ui.Stars.StarsController; @@ -96,7 +96,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; @@ -2957,14 +2956,26 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL messageText = replaceWithLink(messageText, "un2", createTopic.topic); } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionEditTopic) { TLRPC.TL_channelAdminLogEventActionEditTopic editTopic = (TLRPC.TL_channelAdminLogEventActionEditTopic) event.action; - if (editTopic.prev_topic instanceof TLRPC.TL_forumTopic && editTopic.new_topic instanceof TLRPC.TL_forumTopic && - ((TLRPC.TL_forumTopic) editTopic.prev_topic).hidden != ((TLRPC.TL_forumTopic) editTopic.new_topic).hidden) { + if ( + editTopic.prev_topic instanceof TLRPC.TL_forumTopic && editTopic.new_topic instanceof TLRPC.TL_forumTopic && + ((TLRPC.TL_forumTopic) editTopic.prev_topic).hidden != ((TLRPC.TL_forumTopic) editTopic.new_topic).hidden + ) { String text = ((TLRPC.TL_forumTopic) editTopic.new_topic).hidden ? getString(R.string.TopicHidden2) : getString(R.string.TopicShown2); messageText = replaceWithLink(text, "%s", fromUser); + } else if ( + editTopic.prev_topic instanceof TLRPC.TL_forumTopic && editTopic.new_topic instanceof TLRPC.TL_forumTopic && + ((TLRPC.TL_forumTopic) editTopic.prev_topic).closed != ((TLRPC.TL_forumTopic) editTopic.new_topic).closed + ) { + if (((TLRPC.TL_forumTopic) editTopic.new_topic).closed) { + messageText = replaceWithLink(getString(R.string.EventLogClosedTopic), "%s", fromUser); + } else { + messageText = replaceWithLink(getString(R.string.EventLogReopenedTopic), "%s", fromUser); + } + messageText = replaceWithLink(messageText, "un2", editTopic.new_topic); } else { messageText = replaceWithLink( - getString(R.string.EventLogEditTopic), - "un1", fromUser + getString(R.string.EventLogEditTopic), + "un1", fromUser ); messageText = replaceWithLink(messageText, "un2", editTopic.prev_topic); messageText = replaceWithLink(messageText, "un3", editTopic.new_topic); @@ -3267,9 +3278,9 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL private boolean spoiledLoginCode = false; private static Pattern loginCodePattern; public void spoilLoginCode() { // spoil login code from +42777 - if (!spoiledLoginCode && messageText != null && messageOwner != null && messageOwner.entities != null && messageOwner.from_id instanceof TLRPC.TL_peerUser && messageOwner.from_id.user_id == 777000) { + if (!spoiledLoginCode && messageText != null && messageOwner != null && messageOwner.entities != null && messageOwner.from_id instanceof TLRPC.TL_peerUser && (messageOwner.from_id.user_id == 777000 || messageOwner.from_id.user_id == UserObject.VERIFY)) { if (loginCodePattern == null) { - loginCodePattern = Pattern.compile("[\\d\\-]{5,7}"); + loginCodePattern = Pattern.compile("[\\d\\-]{5,8}"); } try { Matcher matcher = loginCodePattern.matcher(messageText); @@ -3373,7 +3384,7 @@ public boolean updateTranslation() { public boolean translated = false; public boolean updateTranslation(boolean force) { - boolean replyUpdated = replyMessageObject != null && replyMessageObject.updateTranslation(force); + boolean replyUpdated = replyMessageObject != null && replyMessageObject != this && replyMessageObject.updateTranslation(force); TranslateController translateController = MessagesController.getInstance(currentAccount).getTranslateController(); if ( TranslateController.isTranslatable(this) && @@ -4014,6 +4025,10 @@ private TLRPC.Chat getChat(AbstractMap chats, LongSparseArray< return chat; } + public void updateMessageText() { + updateMessageText(MessagesController.getInstance(currentAccount).getUsers(), MessagesController.getInstance(currentAccount).getChats(), null, null); + } + private void updateMessageText(AbstractMap users, AbstractMap chats, LongSparseArray sUsers, LongSparseArray sChats) { TLRPC.User fromUser = null; TLRPC.Chat fromChat = null; @@ -4345,6 +4360,25 @@ private void updateMessageText(AbstractMap users, AbstractMap< final long chatId = -DialogObject.getPeerDialogId(action.boost_peer); final TLRPC.Chat chat = getChat(chats, sChats, chatId); messageText = replaceWithLink(AndroidUtilities.replaceTags(LocaleController.formatPluralStringComma("ActionStarGiveawayPrize", (int) action.stars)), "un1", chat); + } else if (messageOwner.action instanceof TLRPC.TL_messageActionStarGift) { + TLRPC.TL_messageActionStarGift action = (TLRPC.TL_messageActionStarGift) messageOwner.action; + if (fromObject instanceof TLRPC.User && ((TLRPC.User) fromObject).self && !action.forceIn) { + TLRPC.User user = getUser(users, sUsers, messageOwner.peer_id.user_id); + messageText = replaceWithLink(AndroidUtilities.replaceTags(getString(R.string.ActionGiftOutbound)), "un1", user); + } else if (fromObject instanceof TLRPC.User && UserObject.isService(((TLRPC.User) fromObject).id)) { + messageText = TextUtils.replace(AndroidUtilities.replaceTags(getString(R.string.ActionGiftInbound)), new String[] {"un1"}, new CharSequence[]{ getString(R.string.StarsTransactionUnknown) }); + } else { + messageText = replaceWithLink(AndroidUtilities.replaceTags(getString(R.string.ActionGiftInbound)), "un1", fromObject); + } + int stars = 0; + if (action.gift != null) { + stars = (int) action.gift.stars; + } + int i = messageText.toString().indexOf("un2"); + if (i != -1) { + SpannableStringBuilder sb = SpannableStringBuilder.valueOf(messageText); + messageText = sb.replace(i, i + 3, LocaleController.formatPluralStringComma("Gift2StarsCount", (int) stars)); + } } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftStars) { if (fromObject instanceof TLRPC.User && ((TLRPC.User) fromObject).self) { TLRPC.User user = getUser(users, sUsers, messageOwner.peer_id.user_id); @@ -5313,7 +5347,7 @@ public void setType() { } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium || messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { contentType = 1; type = TYPE_GIFT_PREMIUM; - } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftStars || messageOwner.action instanceof TLRPC.TL_messageActionPrizeStars) { + } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftStars || messageOwner.action instanceof TLRPC.TL_messageActionStarGift || messageOwner.action instanceof TLRPC.TL_messageActionPrizeStars) { contentType = 1; type = TYPE_GIFT_STARS; } else if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { @@ -5814,7 +5848,7 @@ public String getFileName() { public static String getFileName(TLRPC.Message messageOwner) { if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) { - return FileLoader.getAttachFileName(getDocument(messageOwner)); + return getFileName(getDocument(messageOwner)); } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaPhoto) { ArrayList sizes = getMedia(messageOwner).photo.sizes; if (sizes.size() > 0) { @@ -5824,11 +5858,15 @@ public static String getFileName(TLRPC.Message messageOwner) { } } } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage != null) { - return FileLoader.getAttachFileName(getMedia(messageOwner).webpage.document); + return getFileName(getMedia(messageOwner).webpage.document); } return ""; } + public static String getFileName(TLRPC.Document document) { + return FileLoader.getAttachFileName(document); + } + public static String getFileName(TLRPC.MessageMedia media) { if (media instanceof TLRPC.TL_messageMediaDocument) { return FileLoader.getAttachFileName(media.document); @@ -6723,6 +6761,9 @@ public boolean needDrawShareButton() { if (isRepostPreview) { return false; } + if (getDialogId() == UserObject.VERIFY) { + return false; + } if (isSaved) { long selfId = UserConfig.getInstance(currentAccount).clientUserId; long dialogId = MessageObject.getSavedDialogId(selfId, messageOwner); @@ -7868,6 +7909,8 @@ public boolean needDrawAvatar() { if (getDialogId() < 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-getDialogId()); channelSignatureProfiles = (chat != null && chat.signature_profiles); + } else { + channelSignatureProfiles = getDialogId() == UserObject.VERIFY; } return !isSponsored() && (isFromUser() || isFromGroup() || channelSignatureProfiles || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null); } @@ -7889,6 +7932,8 @@ private boolean needDrawAvatarInternal() { if (getDialogId() < 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-getDialogId()); channelSignatureProfiles = (chat != null && chat.signature_profiles); + } else { + channelSignatureProfiles = getDialogId() == UserObject.VERIFY; } return !isSponsored() && (isFromChat() && isFromUser() || isFromGroup() || channelSignatureProfiles || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null); } @@ -8151,6 +8196,9 @@ public static long getMediaSize(TLRPC.MessageMedia media) { } else { document = media != null ? media.document : null; } + if (media != null && !media.alt_documents.isEmpty()) { + document = VideoPlayer.getDocumentForThumb(UserConfig.selectedAccount, media); + } if (document != null) { return document.size; } @@ -9478,6 +9526,9 @@ public boolean needDrawForwarded() { if (type == MessageObject.TYPE_STORY && !isExpiredStory()) { return true; } + if (getDialogId() == UserObject.VERIFY) { + return false; + } if (isSaved) { if (messageOwner == null || messageOwner.fwd_from == null) return false; final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); @@ -9733,6 +9784,13 @@ public String getForwardedName() { return null; } + public Long getForwardedFromId() { + if (messageOwner == null) return null; + if (messageOwner.fwd_from == null) return null; + if (messageOwner.fwd_from.from_id == null) return null; + return DialogObject.getPeerDialogId(messageOwner.fwd_from.from_id); + } + public int getReplyMsgId() { return messageOwner.reply_to != null ? messageOwner.reply_to.reply_to_msg_id : 0; } @@ -10400,7 +10458,7 @@ public boolean probablyRingtone() { for (int a = 0; a < getDocument().attributes.size(); a++) { TLRPC.DocumentAttribute attribute = getDocument().attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeAudio) { - if (attribute.duration < 60) { + if (attribute.duration < 5) { return true; } } @@ -10972,4 +11030,21 @@ public float getProgress() { return 0f; } + private Boolean videoQualitiesCached; + public TLRPC.Document qualityToSave; + public boolean hasVideoQualities() { + if (videoQualitiesCached == null) { + try { + videoQualitiesCached = messageOwner != null && VideoPlayer.hasQualities(currentAccount, messageOwner.media); + } catch (Exception e) { + FileLog.e(e); + videoQualitiesCached = false; + } + } + return videoQualitiesCached; + } + + public boolean isStarGiftAction() { + return messageOwner != null && messageOwner.action instanceof TLRPC.TL_messageActionStarGift; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 15798a6302..7054de5442 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -35,7 +35,6 @@ import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.view.Gravity; -import android.view.View; import android.widget.FrameLayout; import androidx.annotation.NonNull; @@ -70,7 +69,6 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Business.QuickRepliesController; -import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.ChannelMonetizationLayout; import org.telegram.ui.ChatActivity; @@ -635,6 +633,7 @@ protected boolean useCache(Integer arguments) { public String weatherSearchUsername; public boolean storyWeatherPreload; public boolean starsGiftsEnabled; + public boolean stargiftsBlocked; public long starsPaidReactionAmountMax; public long starsSubscriptionAmountMax; public float starsUsdSellRate1000; @@ -695,6 +694,9 @@ public boolean premiumPurchaseBlocked() { public int chatlistJoinedLimitPremium; public String storiesPosting; public String storiesEntities; + public int stargiftsMessageLengthMax; + public int stargiftsConvertPeriodMax; + public boolean videoIgnoreAltDocuments; public int checkResetLangpack; public boolean folderTags; @@ -819,7 +821,7 @@ public int getChatMaxUniqReactions(long dialogId) { } public boolean isPremiumUser(TLRPC.User currentUser) { - return !premiumFeaturesBlocked() && currentUser.premium; + return !premiumFeaturesBlocked() && currentUser.premium && !isSupportUser(currentUser); } public boolean didPressTranscribeButtonEnough() { @@ -963,6 +965,7 @@ public class SponsoredMessagesInfo { public Integer posts_between; public long loadTime; public boolean loading; + public boolean faked; } private class SendAsPeersInfo { @@ -1547,6 +1550,9 @@ public MessagesController(int num) { chatlistInvitesLimitPremium = mainPreferences.getInt("chatlistInvitesLimitPremium", isTest ? 5 : 20); chatlistJoinedLimitDefault = mainPreferences.getInt("chatlistJoinedLimitDefault", 2); chatlistJoinedLimitPremium = mainPreferences.getInt("chatlistJoinedLimitPremium", isTest ? 5 : 20); + stargiftsMessageLengthMax = mainPreferences.getInt("stargiftsMessageLengthMax", 255); + stargiftsConvertPeriodMax = mainPreferences.getInt("stargiftsConvertPeriodMax", isTest ? 300 : 90 * 86400); + videoIgnoreAltDocuments = mainPreferences.getBoolean("videoIgnoreAltDocuments", false); storiesPosting = mainPreferences.getString("storiesPosting", "enabled"); storiesEntities = mainPreferences.getString("storiesEntities", "premium"); storiesExportNopublicLink = mainPreferences.getBoolean("storiesExportNopublicLink", false); @@ -1592,6 +1598,7 @@ public MessagesController(int num) { weatherSearchUsername = mainPreferences.getString("weatherSearchUsername", "izweatherbot"); storyWeatherPreload = mainPreferences.getBoolean("storyWeatherPreload", true); starsGiftsEnabled = mainPreferences.getBoolean("starsGiftsEnabled", true); + stargiftsBlocked = mainPreferences.getBoolean("stargiftsBlocked", true); // !BuildVars.DEBUG_VERSION); starsPaidReactionAmountMax = mainPreferences.getLong("starsPaidReactionAmountMax", 10_000L); starsSubscriptionAmountMax = mainPreferences.getLong("starsSubscriptionAmountMax", 2500L); starsUsdSellRate1000 = mainPreferences.getFloat("starsUsdSellRate1000", 2000); @@ -3698,6 +3705,39 @@ private void applyAppConfig(TLRPC.TL_jsonObject object) { } break; } + case "stargifts_message_length_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (num.value != stargiftsMessageLengthMax) { + stargiftsMessageLengthMax = (int) num.value; + editor.putInt("stargiftsMessageLengthMax", stargiftsMessageLengthMax); + changed = true; + } + } + break; + } + case "stargifts_convert_period_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (num.value != stargiftsConvertPeriodMax) { + stargiftsConvertPeriodMax = (int) num.value; + editor.putInt("stargiftsConvertPeriodMax", stargiftsConvertPeriodMax); + changed = true; + } + } + break; + } + case "video_ignore_alt_documents": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != videoIgnoreAltDocuments) { + videoIgnoreAltDocuments = bool.value; + editor.putBoolean("videoIgnoreAltDocuments", videoIgnoreAltDocuments); + changed = true; + } + } + break; + } case "stories_posting": { if (value.value instanceof TLRPC.TL_jsonString) { TLRPC.TL_jsonString str = (TLRPC.TL_jsonString) value.value; @@ -4269,6 +4309,17 @@ private void applyAppConfig(TLRPC.TL_jsonObject object) { } break; } + case "stargifts_blocked": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != stargiftsBlocked) { + stargiftsBlocked = bool.value; + editor.putBoolean("stargiftsBlocked", stargiftsBlocked); + changed = true; + } + } + break; + } case "stars_paid_reaction_amount_max": { if (value.value instanceof TLRPC.TL_jsonNumber) { TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; @@ -6814,6 +6865,7 @@ public void loadFullUser(final TLRPC.User user, int classGuid, boolean force, Ut } fullUsers.put(user.id, userFull); getTranslateController().updateDialogFull(user.id); + StarsController.getInstance(currentAccount).invalidateProfileGifts(userFull); loadingFullUsers.remove(user.id); loadedFullUsers.put(user.id, System.currentTimeMillis()); String names = user.first_name + user.last_name + UserObject.getPublicUsername(user); @@ -7964,8 +8016,10 @@ public void deleteUserPhoto(TLRPC.InputPhoto photo) { } TLRPC.UserFull userFull = getUserFull(dialogId); - userFull.profile_photo = photos_photo.photo; - getMessagesStorage().updateUserInfo(userFull, false); + if (userFull != null) { + userFull.profile_photo = photos_photo.photo; + getMessagesStorage().updateUserInfo(userFull, false); + } getUserConfig().getCurrentUser().photo = user1.photo; putUser(user1, false); @@ -9161,6 +9215,7 @@ public void processUserInfo(TLRPC.User user, TLRPC.UserFull info, boolean fromCa if (fullUsers.get(user.id) == null) { fullUsers.put(user.id, info); getTranslateController().updateDialogFull(user.id); + StarsController.getInstance(currentAccount).invalidateProfileGifts(info); int index = blockePeers.indexOfKey(user.id); if (info.blocked) { @@ -17997,6 +18052,8 @@ public boolean processUpdateArray(ArrayList updates, ArrayList { +// info.loading = false; +// getNotificationCenter().postNotificationName(NotificationCenter.didLoadSponsoredMessages, dialogId, info.messages); +// AndroidUtilities.runOnUIThread(() -> { info.faked = false; }, 500); +// }, 1500); +// return null; +// } +// } SponsoredMessagesInfo info = sponsoredMessages.get(dialogId); if (info != null && (info.loading || Math.abs(SystemClock.elapsedRealtime() - info.loadTime) <= 5 * 60 * 1000)) { return info; @@ -19937,7 +20010,7 @@ public void sortDialogs(LongSparseArray chatsDict) { dialogsGroupsOnly.add(d); } else if (d.id != selfId) { dialogsUsersOnly.add(d); - if (!UserObject.isReplyUser(d.id)) { + if (!UserObject.isReplyUser(d.id) && d.id != UserObject.VERIFY) { dialogsForBlock.add(d); } } @@ -21842,9 +21915,9 @@ public static TLRPC.InputMedia toInputMedia(TLRPC.MessageMedia media) { } public void openApp(TLRPC.User bot, int classGuid) { - openApp(null, bot, classGuid, null); + openApp(null, bot, null, classGuid, null); } - public void openApp(BaseFragment _fragment, TLRPC.User bot, int classGuid, Browser.Progress progress) { + public void openApp(BaseFragment _fragment, TLRPC.User bot, String param, int classGuid, Browser.Progress progress) { if (bot == null) return; boolean[] cancelled = new boolean[] { false }; @@ -21866,7 +21939,7 @@ public void openApp(BaseFragment _fragment, TLRPC.User bot, int classGuid, Brows fragment = ((ActionBarLayout) fragment.getParentLayout()).getSheetFragment(); } AndroidUtilities.hideKeyboard(fragment.getFragmentView()); - WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, null, null, BotWebViewAttachedSheet.TYPE_WEB_VIEW_BOT_MAIN, 0, false, null, false, null, bot, 0, false); + WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, null, null, BotWebViewAttachedSheet.TYPE_WEB_VIEW_BOT_MAIN, 0, false, null, false, param, bot, 0, false); if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(props) != null) { return; } @@ -21891,7 +21964,7 @@ public void openApp(BaseFragment _fragment, TLRPC.User bot, int classGuid, Brows } TL_bots.TL_botMenuButton btn = (TL_bots.TL_botMenuButton) botInfo[0].menu_button; AndroidUtilities.hideKeyboard(fragment.getFragmentView()); - WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, btn.text, btn.url, BotWebViewAttachedSheet.TYPE_BOT_MENU_BUTTON, 0, false, null, false, null, bot, 0, false); + WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, btn.text, btn.url, BotWebViewAttachedSheet.TYPE_BOT_MENU_BUTTON, 0, false, null, false, param, bot, 0, false); if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(props) != null) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 696a946daf..bbba1e7e67 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -105,7 +105,7 @@ public class MessagesStorage extends BaseController { } } - public final static int LAST_DB_VERSION = 156; + public final static int LAST_DB_VERSION = 159; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -726,6 +726,8 @@ public static void createTables(SQLiteDatabase database) throws SQLiteException database.executeFast("CREATE TABLE fact_checks(hash INTEGER PRIMARY KEY, data BLOB, expires INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE popular_bots(uid INTEGER PRIMARY KEY, time INTEGER, offset TEXT);").stepThis().dispose(); + database.executeFast("CREATE TABLE star_gifts2(id INTEGER PRIMARY KEY, data BLOB, hash INTEGER, time INTEGER, pos INTEGER);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = " + MessagesStorage.LAST_DB_VERSION).stepThis().dispose(); } @@ -1407,6 +1409,7 @@ public void clearLocalDatabase() { database.executeFast("DELETE FROM quick_replies_messages").stepThis().dispose(); database.executeFast("DELETE FROM effects").stepThis().dispose(); database.executeFast("DELETE FROM app_config").stepThis().dispose(); + database.executeFast("DELETE FROM star_gifts2").stepThis().dispose(); cursor = database.queryFinalized("SELECT did FROM dialogs WHERE 1"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 5a92701b23..e514aa40d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -264,6 +264,9 @@ public class NotificationCenter { public static final int channelStarsUpdated = totalEvents++; public static final int webViewResolved = totalEvents++; public static final int updateAllMessages = totalEvents++; + public static final int starGiftsLoaded = totalEvents++; + public static final int starUserGiftsLoaded = totalEvents++; + public static final int starGiftSoldOut = totalEvents++; //global public static final int pushMessagesUpdated = totalEvents++; @@ -543,7 +546,7 @@ public void postNotificationNameOnUIThread(final int id, final Object... args) { AndroidUtilities.runOnUIThread(() -> postNotificationName(id, args)); } - public void postNotificationName(int id, Object... args) { + public void postNotificationName(final int id, Object... args) { boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations || id == didReplacedPhotoInMemCache || id == closeChats || id == invalidateMotionBackground || id == needCheckSystemBarColors; ArrayList expiredIndices = null; if (!allowDuringAnimation && allowedNotifications.size() > 0) { @@ -592,20 +595,20 @@ public void postNotificationName(int id, Object... args) { } } - SparseArray alreadyPostedRannubles = new SparseArray<>(); + SparseArray alreadyPostedRunnubles = new SparseArray<>(); private void postNotificationDebounced(int id, Object[] args) { int hash = id + (Arrays.hashCode(args) << 16); - if (alreadyPostedRannubles.indexOfKey(hash) >= 0) { + if (alreadyPostedRunnubles.indexOfKey(hash) >= 0) { //skip - } else { - Runnable runnable = () -> { - postNotificationNameInternal(id, false, args); - alreadyPostedRannubles.remove(hash); - }; - alreadyPostedRannubles.put(hash, runnable); - AndroidUtilities.runOnUIThread(runnable, 250); + return; } + final Runnable runnable = () -> { + postNotificationNameInternal(id, false, args); + alreadyPostedRunnubles.remove(hash); + }; + alreadyPostedRunnubles.put(hash, runnable); + AndroidUtilities.runOnUIThread(runnable, 250); } private boolean shouldDebounce(int id, Object[] args) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 62b284b841..f2ed65d2c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -465,7 +465,9 @@ public boolean hasMessagesToReply() { if (messageObject.isReactionPush || messageObject.messageOwner.mentioned && messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage || DialogObject.isEncryptedDialog(dialog_id) || - messageObject.messageOwner.peer_id.channel_id != 0 && !messageObject.isSupergroup()) { + messageObject.messageOwner.peer_id.channel_id != 0 && !messageObject.isSupergroup() || + dialog_id == UserObject.VERIFY + ) { continue; } return true; @@ -1596,7 +1598,6 @@ public void processLoadedUnreadMessages(LongSparseArray dialogs, ArrayL private int getTotalAllUnreadCount() { int count = 0; - FileLog.d("getTotalAllUnreadCount: init 0"); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { if (!UserConfig.getInstance(a).isClientActivated() || !SharedConfig.showNotificationsForAllAccounts && UserConfig.selectedAccount != a) { continue; @@ -1616,7 +1617,6 @@ private int getTotalAllUnreadCount() { } } if (dialog != null) { - FileLog.d("getTotalAllUnreadCount: account=" + a + " count += getDialogUnreadCount (" + MessagesController.getInstance(a).getDialogUnreadCount(dialog) + ")"); count += MessagesController.getInstance(a).getDialogUnreadCount(dialog); } } @@ -1624,7 +1624,6 @@ private int getTotalAllUnreadCount() { FileLog.e(e); } } else { - FileLog.d("getTotalAllUnreadCount: account=" + a + " count += total_unread_count (" + controller.total_unread_count + ")"); count += controller.total_unread_count; } } else { @@ -1639,7 +1638,6 @@ private int getTotalAllUnreadCount() { } } if (MessagesController.getInstance(a).getDialogUnreadCount(dialog) != 0) { - FileLog.d("getTotalAllUnreadCount: account=" + a + " count++ if getDialogUnreadCount != 0 (" + MessagesController.getInstance(a).getDialogUnreadCount(dialog) + ")"); count++; } } @@ -1648,13 +1646,11 @@ private int getTotalAllUnreadCount() { FileLog.e(e, false); } } else { - FileLog.d("getTotalAllUnreadCount: account=" + a + " count += controller.pushDialogs (" + controller.pushDialogs.size() + ")"); count += controller.pushDialogs.size(); } } } } - FileLog.d("getTotalAllUnreadCount: total is " + count); return count; } @@ -1705,9 +1701,9 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us preview[0] = false; } if (messageObject.messageOwner.peer_id.channel_id != 0 && !messageObject.isSupergroup()) { - return LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, messageObject.localName); + return LocaleController.formatString(R.string.ChannelMessageNoText, messageObject.localName); } else { - return LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, messageObject.localUserName, messageObject.localName); + return LocaleController.formatString(R.string.NotificationMessageGroupNoText, messageObject.localUserName, messageObject.localName); } } } @@ -1800,14 +1796,16 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { return messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp) { - return LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, name); + return LocaleController.formatString(R.string.NotificationContactJoined, name); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { - return LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, name); + return LocaleController.formatString(R.string.NotificationContactNewPhoto, name); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) { - String date = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().getFormatterYear().format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().getFormatterDay().format(((long) messageObject.messageOwner.date) * 1000)); - return LocaleController.formatString("NotificationUnrecognizedDevice", R.string.NotificationUnrecognizedDevice, getUserConfig().getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address); + String date = LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterYear().format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().getFormatterDay().format(((long) messageObject.messageOwner.date) * 1000)); + return LocaleController.formatString(R.string.NotificationUnrecognizedDevice, getUserConfig().getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { return messageObject.messageText.toString(); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { + return messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { if (messageObject.messageOwner.action.video) { return LocaleController.getString(R.string.CallMessageVideoIncomingMissed); @@ -1821,10 +1819,10 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } if (singleUserId != 0) { if (messageObject.messageOwner.peer_id.channel_id != 0 && !chat.megagroup) { - return LocaleController.formatString("ChannelAddedByNotification", R.string.ChannelAddedByNotification, name, chat.title); + return LocaleController.formatString(R.string.ChannelAddedByNotification, name, chat.title); } else { if (singleUserId == selfUsedId) { - return LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, name, chat.title); + return LocaleController.formatString(R.string.NotificationInvitedToGroup, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(singleUserId); if (u2 == null) { @@ -1832,12 +1830,12 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } if (fromId == u2.id) { if (chat.megagroup) { - return LocaleController.formatString("NotificationGroupAddSelfMega", R.string.NotificationGroupAddSelfMega, name, chat.title); + return LocaleController.formatString(R.string.NotificationGroupAddSelfMega, name, chat.title); } else { - return LocaleController.formatString("NotificationGroupAddSelf", R.string.NotificationGroupAddSelf, name, chat.title); + return LocaleController.formatString(R.string.NotificationGroupAddSelf, name, chat.title); } } else { - return LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, UserObject.getUserName(u2)); + return LocaleController.formatString(R.string.NotificationGroupAddMember, name, chat.title, UserObject.getUserName(u2)); } } } @@ -1853,10 +1851,14 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us names.append(name2); } } - return LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, names.toString()); + return LocaleController.formatString(R.string.NotificationGroupAddMember, name, chat.title, names.toString()); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGroupCall) { - return LocaleController.formatString("NotificationGroupCreatedCall", R.string.NotificationGroupCreatedCall, name, chat.title); + if (messageObject.messageOwner.action.duration != 0) { + return LocaleController.formatString(R.string.NotificationGroupEndedCall, name, chat.title); + } else { + return LocaleController.formatString(R.string.NotificationGroupCreatedCall, name, chat.title); + } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGroupCallScheduled) { return messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionInviteToGroupCall) { @@ -1866,13 +1868,13 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } if (singleUserId != 0) { if (singleUserId == selfUsedId) { - return LocaleController.formatString("NotificationGroupInvitedYouToCall", R.string.NotificationGroupInvitedYouToCall, name, chat.title); + return LocaleController.formatString(R.string.NotificationGroupInvitedYouToCall, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(singleUserId); if (u2 == null) { return null; } - return LocaleController.formatString("NotificationGroupInvitedToCall", R.string.NotificationGroupInvitedToCall, name, chat.title, UserObject.getUserName(u2)); + return LocaleController.formatString(R.string.NotificationGroupInvitedToCall, name, chat.title, UserObject.getUserName(u2)); } } else { StringBuilder names = new StringBuilder(); @@ -1886,48 +1888,48 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us names.append(name2); } } - return LocaleController.formatString("NotificationGroupInvitedToCall", R.string.NotificationGroupInvitedToCall, name, chat.title, names.toString()); + return LocaleController.formatString(R.string.NotificationGroupInvitedToCall, name, chat.title, names.toString()); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { return LocaleController.getString(R.string.BoostingReceivedGiftNoName); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink) { - return LocaleController.formatString("NotificationInvitedToGroupByLink", R.string.NotificationInvitedToGroupByLink, name, chat.title); + return LocaleController.formatString(R.string.NotificationInvitedToGroupByLink, name, chat.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditTitle) { - return LocaleController.formatString("NotificationEditedGroupName", R.string.NotificationEditedGroupName, name, messageObject.messageOwner.action.title); + return LocaleController.formatString(R.string.NotificationEditedGroupName, name, messageObject.messageOwner.action.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeletePhoto) { if (messageObject.messageOwner.peer_id.channel_id != 0 && !chat.megagroup) { if (messageObject.isVideoAvatar()) { - return LocaleController.formatString("ChannelVideoEditNotification", R.string.ChannelVideoEditNotification, chat.title); + return LocaleController.formatString(R.string.ChannelVideoEditNotification, chat.title); } else { - return LocaleController.formatString("ChannelPhotoEditNotification", R.string.ChannelPhotoEditNotification, chat.title); + return LocaleController.formatString(R.string.ChannelPhotoEditNotification, chat.title); } } else { if (messageObject.isVideoAvatar()) { - return LocaleController.formatString("NotificationEditedGroupVideo", R.string.NotificationEditedGroupVideo, name, chat.title); + return LocaleController.formatString(R.string.NotificationEditedGroupVideo, name, chat.title); } else { - return LocaleController.formatString("NotificationEditedGroupPhoto", R.string.NotificationEditedGroupPhoto, name, chat.title); + return LocaleController.formatString(R.string.NotificationEditedGroupPhoto, name, chat.title); } } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser) { if (messageObject.messageOwner.action.user_id == selfUsedId) { - return LocaleController.formatString("NotificationGroupKickYou", R.string.NotificationGroupKickYou, name, chat.title); + return LocaleController.formatString(R.string.NotificationGroupKickYou, name, chat.title); } else if (messageObject.messageOwner.action.user_id == fromId) { - return LocaleController.formatString("NotificationGroupLeftMember", R.string.NotificationGroupLeftMember, name, chat.title); + return LocaleController.formatString(R.string.NotificationGroupLeftMember, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(messageObject.messageOwner.action.user_id); if (u2 == null) { return null; } - return LocaleController.formatString("NotificationGroupKickMember", R.string.NotificationGroupKickMember, name, chat.title, UserObject.getUserName(u2)); + return LocaleController.formatString(R.string.NotificationGroupKickMember, name, chat.title, UserObject.getUserName(u2)); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatCreate) { return messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChannelCreate) { return messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatMigrateTo) { - return LocaleController.formatString("ActionMigrateFromGroupNotify", R.string.ActionMigrateFromGroupNotify, chat.title); + return LocaleController.formatString(R.string.ActionMigrateFromGroupNotify, chat.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { - return LocaleController.formatString("ActionMigrateFromGroupNotify", R.string.ActionMigrateFromGroupNotify, messageObject.messageOwner.action.title); + return LocaleController.formatString(R.string.ActionMigrateFromGroupNotify, messageObject.messageOwner.action.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionScreenshotTaken) { return messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiveawayLaunch) { @@ -1937,218 +1939,218 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { if (chat != null && (!ChatObject.isChannel(chat) || chat.megagroup)) { if (messageObject.replyMessageObject == null) { - return LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedNoText, name, chat.title); } else { MessageObject object = messageObject.replyMessageObject; if (object.isMusic()) { - return LocaleController.formatString("NotificationActionPinnedMusic", R.string.NotificationActionPinnedMusic, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedMusic, name, chat.title); } else if (object.isVideo()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCF9 " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - return LocaleController.formatString("NotificationActionPinnedVideo", R.string.NotificationActionPinnedVideo, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedVideo, name, chat.title); } } else if (object.isGif()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83C\uDFAC " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - return LocaleController.formatString("NotificationActionPinnedGif", R.string.NotificationActionPinnedGif, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGif, name, chat.title); } } else if (object.isVoice()) { - return LocaleController.formatString("NotificationActionPinnedVoice", R.string.NotificationActionPinnedVoice, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedVoice, name, chat.title); } else if (object.isRoundVideo()) { - return LocaleController.formatString("NotificationActionPinnedRound", R.string.NotificationActionPinnedRound, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedRound, name, chat.title); } else if (object.isSticker() || object.isAnimatedSticker()) { String emoji = object.getStickerEmoji(); if (emoji != null) { - return LocaleController.formatString("NotificationActionPinnedStickerEmoji", R.string.NotificationActionPinnedStickerEmoji, name, chat.title, emoji); + return LocaleController.formatString(R.string.NotificationActionPinnedStickerEmoji, name, chat.title, emoji); } else { - return LocaleController.formatString("NotificationActionPinnedSticker", R.string.NotificationActionPinnedSticker, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedSticker, name, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCCE " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - return LocaleController.formatString("NotificationActionPinnedFile", R.string.NotificationActionPinnedFile, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedFile, name, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - return LocaleController.formatString("NotificationActionPinnedGeo", R.string.NotificationActionPinnedGeo, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGeo, name, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - return LocaleController.formatString("NotificationActionPinnedGeoLive", R.string.NotificationActionPinnedGeoLive, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGeoLive, name, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) object.messageOwner.media; - return LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + return LocaleController.formatString(R.string.NotificationActionPinnedContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - return LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); + return LocaleController.formatString(R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question.text); + return LocaleController.formatString(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)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - return LocaleController.formatString("NotificationActionPinnedPhoto", R.string.NotificationActionPinnedPhoto, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedPhoto, name, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - return LocaleController.formatString("NotificationActionPinnedGame", R.string.NotificationActionPinnedGame, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGame, name, chat.title); } else if (object.messageText != null && object.messageText.length() > 0) { CharSequence message = object.messageText; if (message.length() > 20) { message = message.subSequence(0, 20) + "..."; } - return LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - return LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedNoText, name, chat.title); } } } else if (chat != null) { if (messageObject.replyMessageObject == null) { - return LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedNoTextChannel, chat.title); } else { MessageObject object = messageObject.replyMessageObject; if (object.isMusic()) { - return LocaleController.formatString("NotificationActionPinnedMusicChannel", R.string.NotificationActionPinnedMusicChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedMusicChannel, chat.title); } else if (object.isVideo()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCF9 " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - return LocaleController.formatString("NotificationActionPinnedVideoChannel", R.string.NotificationActionPinnedVideoChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedVideoChannel, chat.title); } } else if (object.isGif()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83C\uDFAC " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - return LocaleController.formatString("NotificationActionPinnedGifChannel", R.string.NotificationActionPinnedGifChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGifChannel, chat.title); } } else if (object.isVoice()) { - return LocaleController.formatString("NotificationActionPinnedVoiceChannel", R.string.NotificationActionPinnedVoiceChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedVoiceChannel, chat.title); } else if (object.isRoundVideo()) { - return LocaleController.formatString("NotificationActionPinnedRoundChannel", R.string.NotificationActionPinnedRoundChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedRoundChannel, chat.title); } else if (object.isSticker() || object.isAnimatedSticker()) { String emoji = object.getStickerEmoji(); if (emoji != null) { - return LocaleController.formatString("NotificationActionPinnedStickerEmojiChannel", R.string.NotificationActionPinnedStickerEmojiChannel, chat.title, emoji); + return LocaleController.formatString(R.string.NotificationActionPinnedStickerEmojiChannel, chat.title, emoji); } else { - return LocaleController.formatString("NotificationActionPinnedStickerChannel", R.string.NotificationActionPinnedStickerChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedStickerChannel, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCCE " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - return LocaleController.formatString("NotificationActionPinnedFileChannel", R.string.NotificationActionPinnedFileChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedFileChannel, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - return LocaleController.formatString("NotificationActionPinnedGeoChannel", R.string.NotificationActionPinnedGeoChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGeoChannel, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - return LocaleController.formatString("NotificationActionPinnedGeoLiveChannel", R.string.NotificationActionPinnedGeoLiveChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGeoLiveChannel, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) object.messageOwner.media; - return LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + return LocaleController.formatString(R.string.NotificationActionPinnedContactChannel2, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - return LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); + return LocaleController.formatString(R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question.text); + return LocaleController.formatString(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)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - return LocaleController.formatString("NotificationActionPinnedPhotoChannel", R.string.NotificationActionPinnedPhotoChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedPhotoChannel, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - return LocaleController.formatString("NotificationActionPinnedGameChannel", R.string.NotificationActionPinnedGameChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedGameChannel, chat.title); } else if (object.messageText != null && object.messageText.length() > 0) { CharSequence message = object.messageText; if (message.length() > 20) { message = message.subSequence(0, 20) + "..."; } - return LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - return LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); + return LocaleController.formatString(R.string.NotificationActionPinnedNoTextChannel, chat.title); } } } else { if (messageObject.replyMessageObject == null) { - return LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedNoTextUser, name); } else { MessageObject object = messageObject.replyMessageObject; if (object.isMusic()) { - return LocaleController.formatString("NotificationActionPinnedMusicUser", R.string.NotificationActionPinnedMusicUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedMusicUser, name); } else if (object.isVideo()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCF9 " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextUser, name, message); } else { - return LocaleController.formatString("NotificationActionPinnedVideoUser", R.string.NotificationActionPinnedVideoUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedVideoUser, name); } } else if (object.isGif()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83C\uDFAC " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextUser, name, message); } else { - return LocaleController.formatString("NotificationActionPinnedGifUser", R.string.NotificationActionPinnedGifUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedGifUser, name); } } else if (object.isVoice()) { - return LocaleController.formatString("NotificationActionPinnedVoiceUser", R.string.NotificationActionPinnedVoiceUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedVoiceUser, name); } else if (object.isRoundVideo()) { - return LocaleController.formatString("NotificationActionPinnedRoundUser", R.string.NotificationActionPinnedRoundUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedRoundUser, name); } else if (object.isSticker() || object.isAnimatedSticker()) { String emoji = object.getStickerEmoji(); if (emoji != null) { - return LocaleController.formatString("NotificationActionPinnedStickerEmojiUser", R.string.NotificationActionPinnedStickerEmojiUser, name, emoji); + return LocaleController.formatString(R.string.NotificationActionPinnedStickerEmojiUser, name, emoji); } else { - return LocaleController.formatString("NotificationActionPinnedStickerUser", R.string.NotificationActionPinnedStickerUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedStickerUser, name); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCCE " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextUser, name, message); } else { - return LocaleController.formatString("NotificationActionPinnedFileUser", R.string.NotificationActionPinnedFileUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedFileUser, name); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - return LocaleController.formatString("NotificationActionPinnedGeoUser", R.string.NotificationActionPinnedGeoUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedGeoUser, name); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - return LocaleController.formatString("NotificationActionPinnedGeoLiveUser", R.string.NotificationActionPinnedGeoLiveUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedGeoLiveUser, name); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) object.messageOwner.media; - return LocaleController.formatString("NotificationActionPinnedContactUser", R.string.NotificationActionPinnedContactUser, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + return LocaleController.formatString(R.string.NotificationActionPinnedContactUser, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - return LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question.text); + return LocaleController.formatString(R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question.text); + return LocaleController.formatString(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)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; - return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextUser, name, message); } else { - return LocaleController.formatString("NotificationActionPinnedPhotoUser", R.string.NotificationActionPinnedPhotoUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedPhotoUser, name); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - return LocaleController.formatString("NotificationActionPinnedGameUser", R.string.NotificationActionPinnedGameUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedGameUser, name); } else if (object.messageText != null && object.messageText.length() > 0) { CharSequence message = object.messageText; if (message.length() > 20) { message = message.subSequence(0, 20) + "..."; } - return LocaleController.formatString("NotificationActionPinnedTextUser", R.string.NotificationActionPinnedTextUser, name, message); + return LocaleController.formatString(R.string.NotificationActionPinnedTextUser, name, message); } else { - return LocaleController.formatString("NotificationActionPinnedNoTextUser", R.string.NotificationActionPinnedNoTextUser, name); + return LocaleController.formatString(R.string.NotificationActionPinnedNoTextUser, name); } } } @@ -2156,12 +2158,12 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us String emoticon = ((TLRPC.TL_messageActionSetChatTheme) messageObject.messageOwner.action).emoticon; if (TextUtils.isEmpty(emoticon)) { msg = dialogId == selfUsedId - ? LocaleController.formatString("ChatThemeDisabledYou", R.string.ChatThemeDisabledYou) + ? LocaleController.formatString(R.string.ChatThemeDisabledYou) : LocaleController.formatString("ChatThemeDisabled", R.string.ChatThemeDisabled, name, emoticon); } else { msg = dialogId == selfUsedId - ? LocaleController.formatString("ChangedChatThemeYou", R.string.ChatThemeChangedYou, emoticon) - : LocaleController.formatString("ChangedChatThemeTo", R.string.ChatThemeChangedTo, name, emoticon); + ? LocaleController.formatString(R.string.ChatThemeChangedYou, emoticon) + : LocaleController.formatString(R.string.ChatThemeChangedTo, name, emoticon); } return msg; } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) { @@ -2268,7 +2270,7 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaStory) { TLRPC.TL_messageMediaStory storyMedia = (TLRPC.TL_messageMediaStory) messageObject.messageOwner.media; if (storyMedia.via_mention) { - return LocaleController.formatString("StoryNotificationMention", R.string.StoryNotificationMention, userName[0] == null ? "" : userName[0]); + return LocaleController.formatString(R.string.StoryNotificationMention, userName[0] == null ? "" : userName[0]); } else { return LocaleController.getString(R.string.Story); } @@ -2289,7 +2291,7 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } char[] spoilerChars = new char[] { - '⠌', '⡢', '⢑','⠨', + '⠌', '⡢', '⢑', '⠨', '⠥', '⠮', '⡑' }; private String replaceSpoilers(MessageObject messageObject) { @@ -2301,6 +2303,9 @@ private String replaceSpoilers(MessageObject messageObject) { return null; } StringBuilder stringBuilder = new StringBuilder(text); + if (messageObject != null && messageObject.didSpoilLoginCode()) { + return stringBuilder.toString(); + } for (int i = 0; i < messageObject.messageOwner.entities.size(); i++) { if (messageObject.messageOwner.entities.get(i) instanceof TLRPC.TL_messageEntitySpoiler) { TLRPC.TL_messageEntitySpoiler spoiler = (TLRPC.TL_messageEntitySpoiler) messageObject.messageOwner.entities.get(i); @@ -2325,6 +2330,10 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes if (preview != null) { preview[0] = true; } + if (messageObject != null && messageObject.getDialogId() == UserObject.VERIFY && messageObject.getForwardedFromId() != null) { + fromId = messageObject.getForwardedFromId(); + chatId = fromId < 0 ? -fromId : 0; + } SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); boolean dialogPreviewEnabled = preferences.getBoolean("content_preview_" + dialogId, true); if (messageObject.isFcmMessage()) { @@ -2333,7 +2342,7 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes if (preview != null) { preview[0] = false; } - return LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, messageObject.localName); + return LocaleController.formatString(R.string.NotificationMessageNoText, messageObject.localName); } } else if (chatId != 0) { if (!dialogPreviewEnabled || !messageObject.localChannel && !preferences.getBoolean("EnablePreviewGroup", true) || messageObject.localChannel && !preferences.getBoolean("EnablePreviewChannel", true)) { @@ -2341,9 +2350,9 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes preview[0] = false; } if (messageObject.messageOwner.peer_id.channel_id != 0 && !messageObject.isSupergroup()) { - return LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, messageObject.localName); + return LocaleController.formatString(R.string.ChannelMessageNoText, messageObject.localName); } else { - return LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, messageObject.localUserName, messageObject.localName); + return LocaleController.formatString(R.string.NotificationMessageGroupNoText, messageObject.localUserName, messageObject.localName); } } } @@ -2414,14 +2423,16 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) { msg = messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp) { - msg = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, name); + msg = LocaleController.formatString(R.string.NotificationContactJoined, name); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { - msg = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, name); + msg = LocaleController.formatString(R.string.NotificationContactNewPhoto, name); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) { - String date = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().getFormatterYear().format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().getFormatterDay().format(((long) messageObject.messageOwner.date) * 1000)); - msg = LocaleController.formatString("NotificationUnrecognizedDevice", R.string.NotificationUnrecognizedDevice, getUserConfig().getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address); + String date = LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterYear().format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().getFormatterDay().format(((long) messageObject.messageOwner.date) * 1000)); + msg = LocaleController.formatString(R.string.NotificationUnrecognizedDevice, getUserConfig().getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { msg = messageObject.messageText.toString(); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { + msg = messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { if (messageObject.messageOwner.action.video) { msg = LocaleController.getString(R.string.CallMessageVideoIncomingMissed); @@ -2432,12 +2443,12 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes String emoticon = ((TLRPC.TL_messageActionSetChatTheme) messageObject.messageOwner.action).emoticon; if (TextUtils.isEmpty(emoticon)) { msg = dialogId == selfUsedId - ? LocaleController.formatString("ChatThemeDisabledYou", R.string.ChatThemeDisabledYou) - : LocaleController.formatString("ChatThemeDisabled", R.string.ChatThemeDisabled, name, emoticon); + ? LocaleController.formatString(R.string.ChatThemeDisabledYou) + : LocaleController.formatString(R.string.ChatThemeDisabled, name, emoticon); } else { msg = dialogId == selfUsedId - ? LocaleController.formatString("ChangedChatThemeYou", R.string.ChatThemeChangedYou, emoticon) - : LocaleController.formatString("ChangedChatThemeTo", R.string.ChatThemeChangedTo, name, emoticon); + ? LocaleController.formatString(R.string.ChatThemeChangedYou, emoticon) + : LocaleController.formatString(R.string.ChatThemeChangedTo, name, emoticon); } text[0] = true; } @@ -2445,92 +2456,92 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes if (messageObject.isMediaEmpty()) { if (!shortMessage) { if (!TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, name); + msg = LocaleController.formatString(R.string.NotificationMessageNoText, name); } } else { - msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, name); + msg = LocaleController.formatString(R.string.NotificationMessageNoText, name); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83D\uDDBC " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83D\uDDBC " + messageObject.messageOwner.message); text[0] = true; } else { if (messageObject.messageOwner.media.ttl_seconds != 0) { - msg = LocaleController.formatString("NotificationMessageSDPhoto", R.string.NotificationMessageSDPhoto, name); + msg = LocaleController.formatString(R.string.NotificationMessageSDPhoto, name); } else { - msg = LocaleController.formatString("NotificationMessagePhoto", R.string.NotificationMessagePhoto, name); + msg = LocaleController.formatString(R.string.NotificationMessagePhoto, name); } } } else if (messageObject.isVideo()) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83D\uDCF9 " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83D\uDCF9 " + messageObject.messageOwner.message); text[0] = true; } else { if (messageObject.messageOwner.media.ttl_seconds != 0) { - msg = LocaleController.formatString("NotificationMessageSDVideo", R.string.NotificationMessageSDVideo, name); + msg = LocaleController.formatString(R.string.NotificationMessageSDVideo, name); } else { - msg = LocaleController.formatString("NotificationMessageVideo", R.string.NotificationMessageVideo, name); + msg = LocaleController.formatString(R.string.NotificationMessageVideo, name); } } } else if (messageObject.isGame()) { - msg = LocaleController.formatString("NotificationMessageGame", R.string.NotificationMessageGame, name, messageObject.messageOwner.media.game.title); + msg = LocaleController.formatString(R.string.NotificationMessageGame, name, messageObject.messageOwner.media.game.title); } else if (messageObject.isVoice()) { - msg = LocaleController.formatString("NotificationMessageAudio", R.string.NotificationMessageAudio, name); + msg = LocaleController.formatString(R.string.NotificationMessageAudio, name); } else if (messageObject.isRoundVideo()) { - msg = LocaleController.formatString("NotificationMessageRound", R.string.NotificationMessageRound, name); + msg = LocaleController.formatString(R.string.NotificationMessageRound, name); } else if (messageObject.isMusic()) { - msg = LocaleController.formatString("NotificationMessageMusic", R.string.NotificationMessageMusic, name); + msg = LocaleController.formatString(R.string.NotificationMessageMusic, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; - msg = LocaleController.formatString("NotificationMessageContact2", R.string.NotificationMessageContact2, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + msg = LocaleController.formatString(R.string.NotificationMessageContact2, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; - msg = LocaleController.formatString("NotificationMessageChannelGiveaway", R.string.NotificationMessageChannelGiveaway, name, giveaway.quantity, giveaway.months); + msg = LocaleController.formatString(R.string.NotificationMessageChannelGiveaway, name, giveaway.quantity, giveaway.months); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveawayResults) { - msg = LocaleController.formatString("BoostingGiveawayResults", R.string.BoostingGiveawayResults); + msg = LocaleController.formatString(R.string.BoostingGiveawayResults); } 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.text); + msg = LocaleController.formatString(R.string.NotificationMessageQuiz2, name, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, name, mediaPoll.poll.question.text); + msg = LocaleController.formatString(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); + msg = LocaleController.formatString(R.string.NotificationMessageMap, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - msg = LocaleController.formatString("NotificationMessageLiveLocation", R.string.NotificationMessageLiveLocation, name); + msg = LocaleController.formatString(R.string.NotificationMessageLiveLocation, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (messageObject.isSticker() || messageObject.isAnimatedSticker()) { String emoji = messageObject.getStickerEmoji(); if (emoji != null) { - msg = LocaleController.formatString("NotificationMessageStickerEmoji", R.string.NotificationMessageStickerEmoji, name, emoji); + msg = LocaleController.formatString(R.string.NotificationMessageStickerEmoji, name, emoji); } else { - msg = LocaleController.formatString("NotificationMessageSticker", R.string.NotificationMessageSticker, name); + msg = LocaleController.formatString(R.string.NotificationMessageSticker, name); } } else if (messageObject.isGif()) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83C\uDFAC " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83C\uDFAC " + messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("NotificationMessageGif", R.string.NotificationMessageGif, name); + msg = LocaleController.formatString(R.string.NotificationMessageGif, name); } } else { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83D\uDCCE " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83D\uDCCE " + messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("NotificationMessageDocument", R.string.NotificationMessageDocument, name); + msg = LocaleController.formatString(R.string.NotificationMessageDocument, name); } } } else { if (!shortMessage && !TextUtils.isEmpty(messageObject.messageText)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, messageObject.messageText); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, messageObject.messageText); text[0] = true; } else { - msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, name); + msg = LocaleController.formatString(R.string.NotificationMessageNoText, name); } } } @@ -2538,7 +2549,7 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes if (preview != null) { preview[0] = false; } - msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, name); + msg = LocaleController.formatString(R.string.NotificationMessageNoText, name); } } else if (chatId != 0) { boolean isChannel = ChatObject.isChannel(chat) && !chat.megagroup; @@ -2551,10 +2562,10 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } if (singleUserId != 0) { if (messageObject.messageOwner.peer_id.channel_id != 0 && !chat.megagroup) { - msg = LocaleController.formatString("ChannelAddedByNotification", R.string.ChannelAddedByNotification, name, chat.title); + msg = LocaleController.formatString(R.string.ChannelAddedByNotification, name, chat.title); } else { if (singleUserId == selfUsedId) { - msg = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationInvitedToGroup, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(singleUserId); if (u2 == null) { @@ -2562,12 +2573,12 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } if (fromId == u2.id) { if (chat.megagroup) { - msg = LocaleController.formatString("NotificationGroupAddSelfMega", R.string.NotificationGroupAddSelfMega, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationGroupAddSelfMega, name, chat.title); } else { - msg = LocaleController.formatString("NotificationGroupAddSelf", R.string.NotificationGroupAddSelf, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationGroupAddSelf, name, chat.title); } } else { - msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, UserObject.getUserName(u2)); + msg = LocaleController.formatString(R.string.NotificationGroupAddMember, name, chat.title, UserObject.getUserName(u2)); } } } @@ -2583,10 +2594,14 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes names.append(name2); } } - msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, names.toString()); + msg = LocaleController.formatString(R.string.NotificationGroupAddMember, name, chat.title, names.toString()); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGroupCall) { - msg = LocaleController.formatString("NotificationGroupCreatedCall", R.string.NotificationGroupCreatedCall, name, chat.title); + if (messageObject.messageOwner.action.duration != 0) { + return LocaleController.formatString(R.string.NotificationGroupEndedCall, name, chat.title); + } else { + return LocaleController.formatString(R.string.NotificationGroupCreatedCall, name, chat.title); + } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGroupCallScheduled) { msg = messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionInviteToGroupCall) { @@ -2596,13 +2611,13 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } if (singleUserId != 0) { if (singleUserId == selfUsedId) { - msg = LocaleController.formatString("NotificationGroupInvitedYouToCall", R.string.NotificationGroupInvitedYouToCall, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationGroupInvitedYouToCall, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(singleUserId); if (u2 == null) { return null; } - msg = LocaleController.formatString("NotificationGroupInvitedToCall", R.string.NotificationGroupInvitedToCall, name, chat.title, UserObject.getUserName(u2)); + msg = LocaleController.formatString(R.string.NotificationGroupInvitedToCall, name, chat.title, UserObject.getUserName(u2)); } } else { StringBuilder names = new StringBuilder(); @@ -2616,7 +2631,7 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes names.append(name2); } } - msg = LocaleController.formatString("NotificationGroupInvitedToCall", R.string.NotificationGroupInvitedToCall, name, chat.title, names.toString()); + msg = LocaleController.formatString(R.string.NotificationGroupInvitedToCall, name, chat.title, names.toString()); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { TLRPC.TL_messageActionGiftCode giftCode = (TLRPC.TL_messageActionGiftCode) messageObject.messageOwner.action; @@ -2625,191 +2640,191 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes if (from == null) { msg = LocaleController.getString(R.string.BoostingReceivedGiftNoName); } else { - msg = LocaleController.formatString("NotificationMessageGiftCode", R.string.NotificationMessageGiftCode, from, LocaleController.formatPluralString("Months", giftCode.months)); + msg = LocaleController.formatString(R.string.NotificationMessageGiftCode, from, LocaleController.formatPluralString("Months", giftCode.months)); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink) { - msg = LocaleController.formatString("NotificationInvitedToGroupByLink", R.string.NotificationInvitedToGroupByLink, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationInvitedToGroupByLink, name, chat.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditTitle) { - msg = LocaleController.formatString("NotificationEditedGroupName", R.string.NotificationEditedGroupName, name, messageObject.messageOwner.action.title); + msg = LocaleController.formatString(R.string.NotificationEditedGroupName, name, messageObject.messageOwner.action.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeletePhoto) { if (messageObject.messageOwner.peer_id.channel_id != 0 && !chat.megagroup) { if (messageObject.isVideoAvatar()) { - msg = LocaleController.formatString("ChannelVideoEditNotification", R.string.ChannelVideoEditNotification, chat.title); + msg = LocaleController.formatString(R.string.ChannelVideoEditNotification, chat.title); } else { - msg = LocaleController.formatString("ChannelPhotoEditNotification", R.string.ChannelPhotoEditNotification, chat.title); + msg = LocaleController.formatString(R.string.ChannelPhotoEditNotification, chat.title); } } else { if (messageObject.isVideoAvatar()) { - msg = LocaleController.formatString("NotificationEditedGroupVideo", R.string.NotificationEditedGroupVideo, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationEditedGroupVideo, name, chat.title); } else { - msg = LocaleController.formatString("NotificationEditedGroupPhoto", R.string.NotificationEditedGroupPhoto, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationEditedGroupPhoto, name, chat.title); } } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser) { if (messageObject.messageOwner.action.user_id == selfUsedId) { - msg = LocaleController.formatString("NotificationGroupKickYou", R.string.NotificationGroupKickYou, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationGroupKickYou, name, chat.title); } else if (messageObject.messageOwner.action.user_id == fromId) { - msg = LocaleController.formatString("NotificationGroupLeftMember", R.string.NotificationGroupLeftMember, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationGroupLeftMember, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(messageObject.messageOwner.action.user_id); if (u2 == null) { return null; } - msg = LocaleController.formatString("NotificationGroupKickMember", R.string.NotificationGroupKickMember, name, chat.title, UserObject.getUserName(u2)); + msg = LocaleController.formatString(R.string.NotificationGroupKickMember, name, chat.title, UserObject.getUserName(u2)); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatCreate) { msg = messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChannelCreate) { msg = messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatMigrateTo) { - msg = LocaleController.formatString("ActionMigrateFromGroupNotify", R.string.ActionMigrateFromGroupNotify, chat.title); + msg = LocaleController.formatString(R.string.ActionMigrateFromGroupNotify, chat.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { - msg = LocaleController.formatString("ActionMigrateFromGroupNotify", R.string.ActionMigrateFromGroupNotify, messageObject.messageOwner.action.title); + msg = LocaleController.formatString(R.string.ActionMigrateFromGroupNotify, messageObject.messageOwner.action.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionScreenshotTaken) { msg = messageObject.messageText.toString(); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { if (!ChatObject.isChannel(chat) || chat.megagroup) { if (messageObject.replyMessageObject == null) { - msg = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedNoText, name, chat.title); } else { MessageObject object = messageObject.replyMessageObject; if (object.isMusic()) { - msg = LocaleController.formatString("NotificationActionPinnedMusic", R.string.NotificationActionPinnedMusic, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedMusic, name, chat.title); } else if (object.isVideo()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCF9 " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - msg = LocaleController.formatString("NotificationActionPinnedVideo", R.string.NotificationActionPinnedVideo, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedVideo, name, chat.title); } } else if (object.isGif()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83C\uDFAC " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - msg = LocaleController.formatString("NotificationActionPinnedGif", R.string.NotificationActionPinnedGif, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGif, name, chat.title); } } else if (object.isVoice()) { - msg = LocaleController.formatString("NotificationActionPinnedVoice", R.string.NotificationActionPinnedVoice, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedVoice, name, chat.title); } else if (object.isRoundVideo()) { - msg = LocaleController.formatString("NotificationActionPinnedRound", R.string.NotificationActionPinnedRound, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedRound, name, chat.title); } else if (object.isSticker() || object.isAnimatedSticker()) { String emoji = object.getStickerEmoji(); if (emoji != null) { - msg = LocaleController.formatString("NotificationActionPinnedStickerEmoji", R.string.NotificationActionPinnedStickerEmoji, name, chat.title, emoji); + msg = LocaleController.formatString(R.string.NotificationActionPinnedStickerEmoji, name, chat.title, emoji); } else { - msg = LocaleController.formatString("NotificationActionPinnedSticker", R.string.NotificationActionPinnedSticker, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedSticker, name, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCCE " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - msg = LocaleController.formatString("NotificationActionPinnedFile", R.string.NotificationActionPinnedFile, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedFile, name, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - msg = LocaleController.formatString("NotificationActionPinnedGeo", R.string.NotificationActionPinnedGeo, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGeo, name, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - msg = LocaleController.formatString("NotificationActionPinnedGeoLive", R.string.NotificationActionPinnedGeoLive, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGeoLive, name, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; - msg = LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + msg = LocaleController.formatString(R.string.NotificationActionPinnedContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); + msg = LocaleController.formatString(R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question.text); + msg = LocaleController.formatString(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)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - msg = LocaleController.formatString("NotificationActionPinnedPhoto", R.string.NotificationActionPinnedPhoto, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedPhoto, name, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - msg = LocaleController.formatString("NotificationActionPinnedGame", R.string.NotificationActionPinnedGame, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGame, name, chat.title); } else if (object.messageText != null && object.messageText.length() > 0) { CharSequence message = object.messageText; if (message.length() > 20) { message = message.subSequence(0, 20) + "..."; } - msg = LocaleController.formatString("NotificationActionPinnedText", R.string.NotificationActionPinnedText, name, message, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedText, name, message, chat.title); } else { - msg = LocaleController.formatString("NotificationActionPinnedNoText", R.string.NotificationActionPinnedNoText, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedNoText, name, chat.title); } } } else { if (messageObject.replyMessageObject == null) { - msg = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedNoTextChannel, chat.title); } else { MessageObject object = messageObject.replyMessageObject; if (object.isMusic()) { - msg = LocaleController.formatString("NotificationActionPinnedMusicChannel", R.string.NotificationActionPinnedMusicChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedMusicChannel, chat.title); } else if (object.isVideo()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCF9 " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + msg = LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - msg = LocaleController.formatString("NotificationActionPinnedVideoChannel", R.string.NotificationActionPinnedVideoChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedVideoChannel, chat.title); } } else if (object.isGif()) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83C\uDFAC " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + msg = LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - msg = LocaleController.formatString("NotificationActionPinnedGifChannel", R.string.NotificationActionPinnedGifChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGifChannel, chat.title); } } else if (object.isVoice()) { - msg = LocaleController.formatString("NotificationActionPinnedVoiceChannel", R.string.NotificationActionPinnedVoiceChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedVoiceChannel, chat.title); } else if (object.isRoundVideo()) { - msg = LocaleController.formatString("NotificationActionPinnedRoundChannel", R.string.NotificationActionPinnedRoundChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedRoundChannel, chat.title); } else if (object.isSticker() || object.isAnimatedSticker()) { String emoji = object.getStickerEmoji(); if (emoji != null) { - msg = LocaleController.formatString("NotificationActionPinnedStickerEmojiChannel", R.string.NotificationActionPinnedStickerEmojiChannel, chat.title, emoji); + msg = LocaleController.formatString(R.string.NotificationActionPinnedStickerEmojiChannel, chat.title, emoji); } else { - msg = LocaleController.formatString("NotificationActionPinnedStickerChannel", R.string.NotificationActionPinnedStickerChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedStickerChannel, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDCCE " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + msg = LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - msg = LocaleController.formatString("NotificationActionPinnedFileChannel", R.string.NotificationActionPinnedFileChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedFileChannel, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || object.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - msg = LocaleController.formatString("NotificationActionPinnedGeoChannel", R.string.NotificationActionPinnedGeoChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGeoChannel, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - msg = LocaleController.formatString("NotificationActionPinnedGeoLiveChannel", R.string.NotificationActionPinnedGeoLiveChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGeoLiveChannel, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; - msg = LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + msg = LocaleController.formatString(R.string.NotificationActionPinnedContactChannel2, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); + msg = LocaleController.formatString(R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question.text); + msg = LocaleController.formatString(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)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; - msg = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + msg = LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - msg = LocaleController.formatString("NotificationActionPinnedPhotoChannel", R.string.NotificationActionPinnedPhotoChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedPhotoChannel, chat.title); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - msg = LocaleController.formatString("NotificationActionPinnedGameChannel", R.string.NotificationActionPinnedGameChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedGameChannel, chat.title); } else if (object.messageText != null && object.messageText.length() > 0) { CharSequence message = object.messageText; if (message.length() > 20) { message = message.subSequence(0, 20) + "..."; } - msg = LocaleController.formatString("NotificationActionPinnedTextChannel", R.string.NotificationActionPinnedTextChannel, chat.title, message); + msg = LocaleController.formatString(R.string.NotificationActionPinnedTextChannel, chat.title, message); } else { - msg = LocaleController.formatString("NotificationActionPinnedNoTextChannel", R.string.NotificationActionPinnedNoTextChannel, chat.title); + msg = LocaleController.formatString(R.string.NotificationActionPinnedNoTextChannel, chat.title); } } } @@ -2819,12 +2834,12 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes String emoticon = ((TLRPC.TL_messageActionSetChatTheme) messageObject.messageOwner.action).emoticon; if (TextUtils.isEmpty(emoticon)) { msg = dialogId == selfUsedId - ? LocaleController.formatString("ChatThemeDisabledYou", R.string.ChatThemeDisabledYou) + ? LocaleController.formatString(R.string.ChatThemeDisabledYou) : LocaleController.formatString("ChatThemeDisabled", R.string.ChatThemeDisabled, name, emoticon); } else { msg = dialogId == selfUsedId - ? LocaleController.formatString("ChangedChatThemeYou", R.string.ChatThemeChangedYou, emoticon) - : LocaleController.formatString("ChangedChatThemeTo", R.string.ChatThemeChangedTo, name, emoticon); + ? LocaleController.formatString(R.string.ChatThemeChangedYou, emoticon) + : LocaleController.formatString(R.string.ChatThemeChangedTo, name, emoticon); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) { msg = messageObject.messageText.toString(); @@ -2832,157 +2847,157 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (ChatObject.isChannel(chat) && !chat.megagroup) { if (messageObject.isMediaEmpty()) { if (!shortMessage && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, name); + msg = LocaleController.formatString(R.string.ChannelMessageNoText, name); } } else if (messageObject.type == MessageObject.TYPE_PAID_MEDIA && MessageObject.getMedia(messageObject) instanceof TLRPC.TL_messageMediaPaidMedia) { TLRPC.TL_messageMediaPaidMedia paidMedia = (TLRPC.TL_messageMediaPaidMedia) MessageObject.getMedia(messageObject); msg = LocaleController.formatPluralString("NotificationChannelMessagePaidMedia", (int) paidMedia.stars_amount, chat.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83D\uDDBC " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83D\uDDBC " + messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("ChannelMessagePhoto", R.string.ChannelMessagePhoto, name); + msg = LocaleController.formatString(R.string.ChannelMessagePhoto, name); } } else if (messageObject.isVideo()) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83D\uDCF9 " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83D\uDCF9 " + messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("ChannelMessageVideo", R.string.ChannelMessageVideo, name); + msg = LocaleController.formatString(R.string.ChannelMessageVideo, name); } } else if (messageObject.isVoice()) { - msg = LocaleController.formatString("ChannelMessageAudio", R.string.ChannelMessageAudio, name); + msg = LocaleController.formatString(R.string.ChannelMessageAudio, name); } else if (messageObject.isRoundVideo()) { - msg = LocaleController.formatString("ChannelMessageRound", R.string.ChannelMessageRound, name); + msg = LocaleController.formatString(R.string.ChannelMessageRound, name); } else if (messageObject.isMusic()) { - msg = LocaleController.formatString("ChannelMessageMusic", R.string.ChannelMessageMusic, name); + msg = LocaleController.formatString(R.string.ChannelMessageMusic, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; - msg = LocaleController.formatString("ChannelMessageContact2", R.string.ChannelMessageContact2, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + msg = LocaleController.formatString(R.string.ChannelMessageContact2, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } 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.text); + msg = LocaleController.formatString(R.string.ChannelMessageQuiz2, name, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question.text); + msg = LocaleController.formatString(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; - msg = LocaleController.formatString("NotificationMessageChannelGiveaway", R.string.NotificationMessageChannelGiveaway, chat.title, giveaway.quantity, giveaway.months); + msg = LocaleController.formatString(R.string.NotificationMessageChannelGiveaway, chat.title, giveaway.quantity, giveaway.months); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - msg = LocaleController.formatString("ChannelMessageMap", R.string.ChannelMessageMap, name); + msg = LocaleController.formatString(R.string.ChannelMessageMap, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - msg = LocaleController.formatString("ChannelMessageLiveLocation", R.string.ChannelMessageLiveLocation, name); + msg = LocaleController.formatString(R.string.ChannelMessageLiveLocation, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (messageObject.isSticker() || messageObject.isAnimatedSticker()) { String emoji = messageObject.getStickerEmoji(); if (emoji != null) { - msg = LocaleController.formatString("ChannelMessageStickerEmoji", R.string.ChannelMessageStickerEmoji, name, emoji); + msg = LocaleController.formatString(R.string.ChannelMessageStickerEmoji, name, emoji); } else { - msg = LocaleController.formatString("ChannelMessageSticker", R.string.ChannelMessageSticker, name); + msg = LocaleController.formatString(R.string.ChannelMessageSticker, name); } } else if (messageObject.isGif()) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83C\uDFAC " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83C\uDFAC " + messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("ChannelMessageGIF", R.string.ChannelMessageGIF, name); + msg = LocaleController.formatString(R.string.ChannelMessageGIF, name); } } else { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, "\uD83D\uDCCE " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, "\uD83D\uDCCE " + messageObject.messageOwner.message); text[0] = true; } else { - msg = LocaleController.formatString("ChannelMessageDocument", R.string.ChannelMessageDocument, name); + msg = LocaleController.formatString(R.string.ChannelMessageDocument, name); } } } else { if (!shortMessage && !TextUtils.isEmpty(messageObject.messageText)) { - msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, name, messageObject.messageText); + msg = LocaleController.formatString(R.string.NotificationMessageText, name, messageObject.messageText); text[0] = true; } else { - msg = LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, name); + msg = LocaleController.formatString(R.string.ChannelMessageNoText, name); } } } else { if (messageObject.isMediaEmpty()) { if (!shortMessage && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, name, chat.title, messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageGroupText, name, chat.title, messageObject.messageOwner.message); } else { - msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupNoText, name, chat.title); } } else if (messageObject.type == MessageObject.TYPE_PAID_MEDIA && MessageObject.getMedia(messageObject) instanceof TLRPC.TL_messageMediaPaidMedia) { TLRPC.TL_messageMediaPaidMedia paidMedia = (TLRPC.TL_messageMediaPaidMedia) MessageObject.getMedia(messageObject); msg = LocaleController.formatPluralString("NotificationChatMessagePaidMedia", (int) paidMedia.stars_amount, name, chat.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, name, chat.title, "\uD83D\uDDBC " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageGroupText, name, chat.title, "\uD83D\uDDBC " + messageObject.messageOwner.message); } else { - msg = LocaleController.formatString("NotificationMessageGroupPhoto", R.string.NotificationMessageGroupPhoto, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupPhoto, name, chat.title); } } else if (messageObject.isVideo()) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, name, chat.title, "\uD83D\uDCF9 " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageGroupText, name, chat.title, "\uD83D\uDCF9 " + messageObject.messageOwner.message); } else { - msg = LocaleController.formatString(" ", R.string.NotificationMessageGroupVideo, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupVideo, name, chat.title); } } else if (messageObject.isVoice()) { - msg = LocaleController.formatString("NotificationMessageGroupAudio", R.string.NotificationMessageGroupAudio, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupAudio, name, chat.title); } else if (messageObject.isRoundVideo()) { - msg = LocaleController.formatString("NotificationMessageGroupRound", R.string.NotificationMessageGroupRound, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupRound, name, chat.title); } else if (messageObject.isMusic()) { - msg = LocaleController.formatString("NotificationMessageGroupMusic", R.string.NotificationMessageGroupMusic, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupMusic, name, chat.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; - msg = LocaleController.formatString("NotificationMessageGroupContact2", R.string.NotificationMessageGroupContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); + msg = LocaleController.formatString(R.string.NotificationMessageGroupContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } 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.text); + msg = LocaleController.formatString(R.string.NotificationMessageGroupQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, name, chat.title, mediaPoll.poll.question.text); + msg = LocaleController.formatString(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); + msg = LocaleController.formatString(R.string.NotificationMessageGroupGame, name, chat.title, messageObject.messageOwner.media.game.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; - msg = LocaleController.formatString("NotificationMessageChannelGiveaway", R.string.NotificationMessageChannelGiveaway, chat.title, giveaway.quantity, giveaway.months); + msg = LocaleController.formatString(R.string.NotificationMessageChannelGiveaway, chat.title, giveaway.quantity, giveaway.months); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveawayResults) { - msg = LocaleController.formatString("BoostingGiveawayResults", R.string.BoostingGiveawayResults); + msg = LocaleController.formatString(R.string.BoostingGiveawayResults); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { msg = LocaleController.formatString("NotificationMessageGroupMap", R.string.NotificationMessageGroupMap, name, chat.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - msg = LocaleController.formatString("NotificationMessageGroupLiveLocation", R.string.NotificationMessageGroupLiveLocation, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupLiveLocation, name, chat.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (messageObject.isSticker() || messageObject.isAnimatedSticker()) { String emoji = messageObject.getStickerEmoji(); if (emoji != null) { - msg = LocaleController.formatString("NotificationMessageGroupStickerEmoji", R.string.NotificationMessageGroupStickerEmoji, name, chat.title, emoji); + msg = LocaleController.formatString(R.string.NotificationMessageGroupStickerEmoji, name, chat.title, emoji); } else { - msg = LocaleController.formatString("NotificationMessageGroupSticker", R.string.NotificationMessageGroupSticker, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupSticker, name, chat.title); } } else if (messageObject.isGif()) { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, name, chat.title, "\uD83C\uDFAC " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageGroupText, name, chat.title, "\uD83C\uDFAC " + messageObject.messageOwner.message); } else { - msg = LocaleController.formatString("NotificationMessageGroupGif", R.string.NotificationMessageGroupGif, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupGif, name, chat.title); } } else { if (!shortMessage && Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(messageObject.messageOwner.message)) { - msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, name, chat.title, "\uD83D\uDCCE " + messageObject.messageOwner.message); + msg = LocaleController.formatString(R.string.NotificationMessageGroupText, name, chat.title, "\uD83D\uDCCE " + messageObject.messageOwner.message); } else { - msg = LocaleController.formatString("NotificationMessageGroupDocument", R.string.NotificationMessageGroupDocument, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupDocument, name, chat.title); } } } else { if (!shortMessage && !TextUtils.isEmpty(messageObject.messageText)) { - msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, name, chat.title, messageObject.messageText); + msg = LocaleController.formatString(R.string.NotificationMessageGroupText, name, chat.title, messageObject.messageText); } else { - msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupNoText, name, chat.title); } } } @@ -2991,12 +3006,12 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes preview[0] = false; } if (ChatObject.isChannel(chat) && !chat.megagroup) { - msg = LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, name); + msg = LocaleController.formatString(R.string.ChannelMessageNoText, name); } else if (messageObject.type == MessageObject.TYPE_PAID_MEDIA && MessageObject.getMedia(messageObject) instanceof TLRPC.TL_messageMediaPaidMedia) { TLRPC.TL_messageMediaPaidMedia paidMedia = (TLRPC.TL_messageMediaPaidMedia) MessageObject.getMedia(messageObject); msg = LocaleController.formatPluralString("NotificationMessagePaidMedia", (int) paidMedia.stars_amount, name); } else { - msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, name, chat.title); + msg = LocaleController.formatString(R.string.NotificationMessageGroupNoText, name, chat.title); } } } @@ -3954,6 +3969,15 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { if (lastMessageObject.isFromUser() && (userId == 0 || userId == getUserConfig().getClientUserId())) { userId = lastMessageObject.messageOwner.from_id.user_id; } + if (lastMessageObject != null && lastMessageObject.getDialogId() == UserObject.VERIFY && lastMessageObject.getForwardedFromId() != null) { + if (lastMessageObject.getForwardedFromId() >= 0) { + userId = lastMessageObject.getForwardedFromId(); + chatId = 0; + } else { + userId = 0; + chatId = lastMessageObject.getForwardedFromId(); + } + } TLRPC.User user = getMessagesController().getUser(userId); TLRPC.Chat chat = null; @@ -4027,7 +4051,7 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { if (pushDialogs.size() == 1) { detailText += LocaleController.formatPluralString("NewMessages", total_unread_count); } else { - detailText += LocaleController.formatString("NotificationMessagesPeopleDisplayOrder", R.string.NotificationMessagesPeopleDisplayOrder, LocaleController.formatPluralString("NewMessages", total_unread_count), LocaleController.formatPluralString("FromChats", pushDialogs.size())); + detailText += LocaleController.formatString(R.string.NotificationMessagesPeopleDisplayOrder, LocaleController.formatPluralString("NewMessages", total_unread_count), LocaleController.formatPluralString("FromChats", pushDialogs.size())); } } } else { @@ -4658,12 +4682,12 @@ void call() { FileLog.d("showExtraNotifications: break from holders, count over " + maxCount); break; } - DialogKey dialogKey = sortedDialogs.get(b); - long dialogId; - long topicId; + final DialogKey dialogKey = sortedDialogs.get(b); + final long dialogId; + final long topicId; int maxId; MessageObject lastMessageObject = null; - ArrayList messageObjects; + final ArrayList messageObjects; if (dialogKey.story) { messageObjects = new ArrayList<>(); if (storyPushMessages.isEmpty()) { @@ -4679,18 +4703,18 @@ void call() { } else { dialogId = dialogKey.dialogId; topicId = dialogKey.topicId; - messageObjects = messagesByDialogs.get(dialogId); + messageObjects = messagesByDialogs.get(dialogKey.dialogId); maxId = messageObjects.get(0).getId(); lastMessageObject = messageObjects.get(0); } - Integer internalId = oldIdsWear.get(dialogId); + Integer internalId = oldIdsWear.get(dialogKey.dialogId); if (dialogKey.story) { internalId = Integer.MAX_VALUE - 1; } else if (internalId == null) { - internalId = (int) dialogId + (int) (dialogId >> 32); + internalId = (int) dialogKey.dialogId + (int) (dialogKey.dialogId >> 32); } else { - oldIdsWear.remove(dialogId); + oldIdsWear.remove(dialogKey.dialogId); } int maxDate = 0; @@ -4706,7 +4730,7 @@ void call() { String name; TLRPC.FileLocation photoPath = null; Bitmap avatarBitmap = null; - File avatalFile = null; + File avatarFile = null; boolean canReply; if (dialogKey.story) { @@ -4743,7 +4767,9 @@ void call() { photoPath = user.photo.photo_small; } } - if (UserObject.isReplyUser(dialogId)) { + if (dialogId == UserObject.VERIFY) { + name = LocaleController.getString(R.string.VerifyCodesNotifications); + } else if (UserObject.isReplyUser(dialogId)) { name = LocaleController.getString(R.string.RepliesTitle); } else if (dialogId == selfUserId) { name = LocaleController.getString(R.string.MessageScheduledReminderNotification); @@ -4781,6 +4807,23 @@ void call() { } } } + if (dialogId == UserObject.VERIFY && lastMessageObject != null && lastMessageObject.getForwardedFromId() != null) { + long did = lastMessageObject.getForwardedFromId(); + if (DialogObject.isUserDialog(did)) { + TLRPC.User fwduser = getMessagesController().getUser(did); + if (fwduser.photo != null && fwduser.photo.photo_small != null && fwduser.photo.photo_small.volume_id != 0 && fwduser.photo.photo_small.local_id != 0) { + photoPath = fwduser.photo.photo_small; + } + } else { + TLRPC.Chat fwdchat = getMessagesController().getChat(-did); + if (fwdchat.photo != null && fwdchat.photo.photo_small != null && fwdchat.photo.photo_small.volume_id != 0 && fwdchat.photo.photo_small.local_id != 0) { + photoPath = fwdchat.photo.photo_small; + } + } + } + if (dialogId == UserObject.VERIFY) { + canReply = false; + } } else { canReply = false; if (dialogId != globalSecretChatId) { @@ -4820,18 +4863,18 @@ void call() { } if (photoPath != null) { - avatalFile = getFileLoader().getPathToAttach(photoPath, true); + avatarFile = getFileLoader().getPathToAttach(photoPath, true); if (Build.VERSION.SDK_INT < 28) { BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(photoPath, null, "50_50"); if (img != null) { avatarBitmap = img.getBitmap(); } else { try { - if (avatalFile.exists()) { + if (avatarFile.exists()) { float scaleFactor = 160.0f / AndroidUtilities.dp(50); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = scaleFactor < 1 ? 1 : (int) scaleFactor; - avatarBitmap = BitmapFactory.decodeFile(avatalFile.getAbsolutePath(), options); + avatarBitmap = BitmapFactory.decodeFile(avatarFile.getAbsolutePath(), options); } } catch (Throwable ignore) { @@ -4842,8 +4885,8 @@ void call() { if (chat != null) { Person.Builder personBuilder = new Person.Builder().setName(name); - if (avatalFile != null && avatalFile.exists() && Build.VERSION.SDK_INT >= 28) { - loadRoundAvatar(avatalFile, personBuilder); + if (avatarFile != null && avatarFile.exists() && Build.VERSION.SDK_INT >= 28) { + loadRoundAvatar(avatarFile, personBuilder); } personCache.put(-chat.id, personBuilder.build()); } @@ -4860,9 +4903,9 @@ void call() { RemoteInput remoteInputWear = new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(LocaleController.getString(R.string.Reply)).build(); String replyToString; if (DialogObject.isChatDialog(dialogId)) { - replyToString = LocaleController.formatString("ReplyToGroup", R.string.ReplyToGroup, name); + replyToString = LocaleController.formatString(R.string.ReplyToGroup, name); } else { - replyToString = LocaleController.formatString("ReplyToUser", R.string.ReplyToUser, name); + replyToString = LocaleController.formatString(R.string.ReplyToUser, name); } wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon, replyToString, replyPendingIntent) .setAllowGeneratedReplies(true) @@ -4934,7 +4977,7 @@ void call() { if (hidden) { text.append(LocaleController.formatPluralString("StoryNotificationHidden", storiesCount)); } else if (names.isEmpty()) { - FileLog.d("showExtraNotifications: ["+dialogKey.dialogId+"] continue; story but names is empty"); + FileLog.d("showExtraNotifications: ["+dialogId+"] continue; story but names is empty"); continue; } else if (names.size() == 1) { if (storiesCount == 1) { @@ -4967,11 +5010,13 @@ void call() { final boolean isForum = getMessagesController().isForum(messageObject); final long messageTopicId = MessageObject.getTopicId(currentAccount, messageObject.messageOwner, isForum); if (topicId != messageTopicId) { - FileLog.d("showExtraNotifications: ["+dialogKey.dialogId+"] continue; topic id is not equal: topicId=" + topicId + " messageTopicId=" + messageTopicId + "; selfId=" + getUserConfig().getClientUserId()); + FileLog.d("showExtraNotifications: ["+dialogId+"] continue; topic id is not equal: topicId=" + topicId + " messageTopicId=" + messageTopicId + "; selfId=" + getUserConfig().getClientUserId()); continue; } String message = getShortStringForMessage(messageObject, senderName, preview); - if (dialogId == selfUserId) { + if (dialogId == UserObject.VERIFY && messageObject.getForwardedFromId() != null) { + senderName[0] = getMessagesController().getPeerName(messageObject.getForwardedFromId()); + } else if (dialogId == selfUserId) { senderName[0] = name; } else if (DialogObject.isChatDialog(dialogId) && messageObject.messageOwner.from_scheduled) { senderName[0] = LocaleController.getString(R.string.NotificationMessageScheduledName); @@ -4997,7 +5042,9 @@ void call() { } long uid; - if (DialogObject.isUserDialog(dialogId)) { + if (dialogId == UserObject.VERIFY && messageObject.getForwardedFromId() != null) { + uid = messageObject.getForwardedFromId(); + } else if (DialogObject.isUserDialog(dialogId)) { uid = dialogId; } else if (isChannel) { uid = -dialogId; @@ -5031,7 +5078,7 @@ void call() { if (preview[0] && !DialogObject.isEncryptedDialog(dialogId) && Build.VERSION.SDK_INT >= 28) { File avatar = null; if (DialogObject.isUserDialog(dialogId) || isChannel) { - avatar = avatalFile; + avatar = avatarFile; } else { long fromId = messageObject.getSenderId(); TLRPC.User sender = getMessagesController().getUser(fromId); @@ -5045,6 +5092,19 @@ void call() { avatar = getFileLoader().getPathToAttach(sender.photo.photo_small, true); } } + if (avatar == null && dialogId == UserObject.VERIFY && messageObject.getForwardedFromId() != null) { + if (uid >= 0) { + TLRPC.User sender = getMessagesController().getUser(uid); + if (sender != null && sender.photo != null && sender.photo.photo_small != null && sender.photo.photo_small.volume_id != 0 && sender.photo.photo_small.local_id != 0) { + avatar = getFileLoader().getPathToAttach(sender.photo.photo_small, true); + } + } else { + TLRPC.Chat sender = getMessagesController().getChat(-uid); + if (sender != null && sender.photo != null && sender.photo.photo_small != null && sender.photo.photo_small.volume_id != 0 && sender.photo.photo_small.local_id != 0) { + avatar = getFileLoader().getPathToAttach(sender.photo.photo_small, true); + } + } + } loadRoundAvatar(avatar, personBuilder); } person = personBuilder.build(); @@ -5271,6 +5331,9 @@ void call() { if (dialogKey.story) { dismissIntent.putExtra("story", true); } + if (lastMessageObject != null && lastMessageObject.isStoryReactionPush) { + dismissIntent.putExtra("storyReaction", true); + } builder.setDeleteIntent(PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, dismissIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)); } catch (Exception e) { FileLog.e(e); @@ -5281,11 +5344,37 @@ void call() { builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY); } - if (wearReplyAction != null) { - builder.addAction(wearReplyAction); + TLRPC.TL_keyboardButtonCopy copybutton = null; + if (lastMessageObject != null && lastMessageObject.messageOwner != null && lastMessageObject.messageOwner.reply_markup != null) { + TLRPC.ReplyMarkup reply_markup = lastMessageObject.messageOwner.reply_markup; + for (int i = 0; i < reply_markup.rows.size(); ++i) { + for (int j = 0; j < reply_markup.rows.get(i).buttons.size(); ++j) { + if (reply_markup.rows.get(i).buttons.get(j) instanceof TLRPC.TL_keyboardButtonCopy) { + copybutton = (TLRPC.TL_keyboardButtonCopy) reply_markup.rows.get(i).buttons.get(j); + break; + } + } + if (copybutton != null) break; + } } - if (!waitingForPasscode && !dialogKey.story && (lastMessageObject == null || !lastMessageObject.isStoryReactionPush)) { - builder.addAction(readAction); + if (copybutton != null) { + Intent copyIntent = new Intent(ApplicationLoader.applicationContext, CopyCodeReceiver.class); + copyIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + copyIntent.setAction("org.telegram.messenger.ACTION_COPY_CODE"); + copyIntent.putExtra("text", copybutton.copy_text); + PendingIntent copyPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, copyIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Action copyAction = new NotificationCompat.Action.Builder(R.drawable.msg_copy, copybutton.text, copyPendingIntent) + .setShowsUserInterface(false) + .build(); + builder.addAction(copyAction); + } + if (dialogKey.dialogId != UserObject.VERIFY) { + if (wearReplyAction != null) { + builder.addAction(wearReplyAction); + } + if (!waitingForPasscode && !dialogKey.story && (lastMessageObject == null || !lastMessageObject.isStoryReactionPush)) { + builder.addAction(readAction); + } } if (sortedDialogs.size() == 1 && !TextUtils.isEmpty(summary) && !dialogKey.story) { builder.setSubText(summary); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index 4a92da5123..952666bbca 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -152,6 +152,7 @@ public static void processRemoteMessage(@PushType int pushType, String data, lon buffer.readBytes(strBytes, true); jsonString = new String(strBytes); JSONObject json = new JSONObject(jsonString); +// FileLog.d("FCM DATA: " + jsonString); if (ApplicationLoader.applicationLoaderInstance != null && ApplicationLoader.applicationLoaderInstance.consumePush(currentAccount, json)) { countDownLatch.countDown(); @@ -501,6 +502,12 @@ public static void processRemoteMessage(@PushType int pushType, String data, lon message1 = args[1]; break; } + case "MESSAGE_STARGIFT": { + userName = args[0]; + messageText = LocaleController.formatPluralStringComma("NotificationMessageStarGift", Integer.parseInt(args[1]), args[0]); + message1 = LocaleController.formatPluralStringComma("Gift2Notification", Integer.parseInt(args[1])); + break; + } case "MESSAGE_PAID_MEDIA": { int stars = Integer.parseInt(args[1]); messageText = LocaleController.formatPluralString("NotificationMessagePaidMedia", stars, args[0]); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 5eba00ff2d..6e4fd910fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -7052,8 +7052,17 @@ public void prepareImportHistory(long dialogId, Uri uri, ArrayList mediaUri try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipfile))) { ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) { - if (zipEntry.getName().endsWith(".txt")) { - File newFile = MediaController.createFileInCache(zipEntry.getName(), "txt"); + String name = zipEntry.getName(); + if (name == null) { + zipEntry = zis.getNextEntry(); + continue; + } + int idx = name.lastIndexOf("/"); + if (idx >= 0) { + name = name.substring(idx + 1); + } + if (name.endsWith(".txt")) { + File newFile = MediaController.createFileInCache(name, "txt"); path = newFile.getAbsolutePath(); FileOutputStream fos = new FileOutputStream(newFile); byte[] buffer = new byte[1024]; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 1a1217a4be..78a64b7dfb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -305,6 +305,7 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static boolean playOrderReversed; public static boolean hasCameraCache; public static boolean showNotificationsForAllAccounts = true; + public static boolean debugVideoQualities = false; public static int repeatMode; public static boolean allowBigEmoji; public static boolean useSystemEmoji; @@ -318,7 +319,6 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static int emojiInteractionsHintCount; public static int dayNightThemeSwitchHintCount; public static int callEncryptionHintDisplayedCount; - public static boolean botTabs3DEffect; public static TLRPC.TL_help_appUpdate pendingAppUpdate; public static int pendingAppUpdateBuildVersion; @@ -662,7 +662,7 @@ public static void loadConfig() { photoViewerBlur = preferences.getBoolean("photoViewerBlur", true); multipleReactionsPromoShowed = preferences.getBoolean("multipleReactionsPromoShowed", false); callEncryptionHintDisplayedCount = preferences.getInt("callEncryptionHintDisplayedCount", 0); - botTabs3DEffect = preferences.getBoolean("botTabs3DEffect", true); + debugVideoQualities = preferences.getBoolean("debugVideoQualities", false); loadDebugConfig(preferences); @@ -1092,13 +1092,6 @@ public static void incrementCallEncryptionHintDisplayed(int count) { editor.apply(); } - public static void setBotTabs3DEffect(boolean value) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("botTabs3DEffect", botTabs3DEffect = value); - editor.apply(); - } - public static void toggleLoopStickers() { LiteMode.toggleFlag(LiteMode.FLAG_ANIMATED_STICKERS_CHAT); } @@ -1265,6 +1258,14 @@ public static void toggleBrowserAdaptableColors() { editor.apply(); } + public static void toggleDebugVideoQualities() { + debugVideoQualities = !debugVideoQualities; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("debugVideoQualities", debugVideoQualities); + editor.apply(); + } + public static void toggleLocalInstantView() { onlyLocalInstantView = !onlyLocalInstantView; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 151002867d..2e01e6cf34 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -266,7 +266,7 @@ public void setCurrentUser(TLRPC.User user) { } private void checkPremiumSelf(TLRPC.User oldUser, TLRPC.User newUser) { - if (oldUser == null || (newUser != null && oldUser.premium != newUser.premium)) { + if (oldUser != null && newUser != null && oldUser.premium != newUser.premium) { AndroidUtilities.runOnUIThread(() -> { getMessagesController().updatePremium(newUser.premium); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.currentUserPremiumStatusChanged); @@ -276,6 +276,12 @@ private void checkPremiumSelf(TLRPC.User oldUser, TLRPC.User newUser) { getMediaDataController().loadReactions(false, null); getMessagesController().getStoriesController().invalidateStoryLimit(); }); + } else if (oldUser == null) { + AndroidUtilities.runOnUIThread(() -> { + getMessagesController().updatePremium(newUser.premium); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.currentUserPremiumStatusChanged); + getMediaDataController().loadPremiumPromo(true); + }); } } @@ -553,10 +559,11 @@ public void setDialogsLoadOffset(int folderId, int dialogsLoadOffsetId, int dial } public boolean isPremium() { - if (currentUser == null) { + TLRPC.User user = currentUser; + if (user == null) { return false; } - return currentUser.premium; + return user.premium; } public Long getEmojiStatus() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java index c1031ff70b..65b32f7ae4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java @@ -19,6 +19,7 @@ public class UserObject { public static final long REPLY_BOT = 1271266957L; public static final long ANONYMOUS = 2666000L; + public static final long VERIFY = 489000L; public static boolean isDeleted(TLRPC.User user) { return user == null || user instanceof TLRPC.TL_userDeleted_old2 || user instanceof TLRPC.TL_userEmpty || user.deleted; @@ -151,6 +152,9 @@ public static Long getEmojiStatusDocumentId(TLRPC.EmojiStatus emojiStatus) { if (emojiStatus == null) { return null; } + if (MessagesController.getInstance(UserConfig.selectedAccount).premiumFeaturesBlocked()) { + return null; + } if (emojiStatus instanceof TLRPC.TL_emojiStatus) return ((TLRPC.TL_emojiStatus) emojiStatus).document_id; if (emojiStatus instanceof TLRPC.TL_emojiStatusUntil) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index 28c080baac..833d984c31 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -151,7 +151,10 @@ private void updateBuilderForMessage(MediaController.VideoConvertMessage videoCo return; } boolean isGif = videoConvertMessage.messageObject != null && MessageObject.isGifMessage(videoConvertMessage.messageObject.messageOwner); - if (isGif) { + if (videoConvertMessage.foregroundConversion) { + builder.setTicker(LocaleController.getString(R.string.ConvertingVideo)); + builder.setContentText(LocaleController.getString(R.string.ConvertingVideo)); + } else if (isGif) { builder.setTicker(LocaleController.getString(R.string.SendingGif)); builder.setContentText(LocaleController.getString(R.string.SendingGif)); } else { 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 c0f4007cb8..37e9eac469 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java @@ -10,6 +10,8 @@ import android.content.Context; import android.net.Uri; +import android.util.LongSparseArray; + import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.AssetDataSource; @@ -94,13 +96,15 @@ public ExtendedDefaultDataSource( int readTimeoutMillis, boolean allowCrossProtocolRedirects) { this( - context, - new DefaultHttpDataSource( - userAgent, - connectTimeoutMillis, - readTimeoutMillis, - allowCrossProtocolRedirects, - /* defaultRequestProperties= */ null)); + context, + new DefaultHttpDataSource( + userAgent, + connectTimeoutMillis, + readTimeoutMillis, + allowCrossProtocolRedirects, + /* defaultRequestProperties= */ null), + null + ); } /** @@ -111,68 +115,14 @@ public ExtendedDefaultDataSource( * @param baseDataSource A {@link DataSource} to use for URI schemes other than file, asset and * content. This {@link DataSource} should normally support at least http(s). */ - public ExtendedDefaultDataSource(Context context, DataSource baseDataSource) { + public ExtendedDefaultDataSource(Context context, DataSource baseDataSource, LongSparseArray mtprotoUris) { this.context = context.getApplicationContext(); this.baseDataSource = Assertions.checkNotNull(baseDataSource); transferListeners = new ArrayList<>(); + this.mtprotoUris = mtprotoUris; } - /** - * Constructs a new instance, optionally configured to follow cross-protocol redirects. - * - * @param context A context. - * @param listener An optional listener. - * @param userAgent The User-Agent to use when requesting remote data. - * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP - * to HTTPS and vice versa) are enabled when fetching remote data. - * @deprecated Use {@link #DefaultDataSource(Context, String, boolean)} and {@link - * #addTransferListener(TransferListener)}. - */ - @Deprecated - @SuppressWarnings("deprecation") - public ExtendedDefaultDataSource( - Context context, - @Nullable TransferListener listener, - String userAgent, - boolean allowCrossProtocolRedirects) { - this(context, listener, userAgent, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, - DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, allowCrossProtocolRedirects); - } - - /** - * Constructs a new instance, optionally configured to follow cross-protocol redirects. - * - * @param context A context. - * @param listener An optional listener. - * @param userAgent The User-Agent to use when requesting remote data. - * @param connectTimeoutMillis The connection timeout that should be used when requesting remote - * data, in milliseconds. A timeout of zero is interpreted as an infinite timeout. - * @param readTimeoutMillis The read timeout that should be used when requesting remote data, in - * milliseconds. A timeout of zero is interpreted as an infinite timeout. - * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP - * to HTTPS and vice versa) are enabled when fetching remote data. - * @deprecated Use {@link #DefaultDataSource(Context, String, int, int, boolean)} and {@link - * #addTransferListener(TransferListener)}. - */ - @Deprecated - @SuppressWarnings("deprecation") - public ExtendedDefaultDataSource( - Context context, - @Nullable TransferListener listener, - String userAgent, - int connectTimeoutMillis, - int readTimeoutMillis, - boolean allowCrossProtocolRedirects) { - this( - context, - listener, - new DefaultHttpDataSource( - userAgent, - connectTimeoutMillis, - readTimeoutMillis, - allowCrossProtocolRedirects, - /* defaultRequestProperties= */ null)); - } + private final LongSparseArray mtprotoUris; /** * Constructs a new instance that delegates to a provided {@link DataSource} for URI schemes other @@ -187,8 +137,8 @@ public ExtendedDefaultDataSource( */ @Deprecated public ExtendedDefaultDataSource( - Context context, @Nullable TransferListener listener, DataSource baseDataSource) { - this(context, baseDataSource); + Context context, @Nullable TransferListener listener, DataSource baseDataSource, LongSparseArray mtprotoUris) { + this(context, baseDataSource, mtprotoUris); if (listener != null) { transferListeners.add(listener); baseDataSource.addTransferListener(listener); @@ -210,14 +160,19 @@ public void addTransferListener(TransferListener transferListener) { @Override public long open(DataSpec dataSpec) throws IOException { Assertions.checkState(dataSource == null); + Uri uri = dataSpec.uri; + if ("mtproto".equals(uri.getScheme())) { + final long docId = Long.parseLong(dataSpec.uri.toString().substring("mtproto:".length())); + dataSpec.uri = uri = mtprotoUris.get(docId); + } // Choose the correct source for the scheme. - String scheme = dataSpec.uri.getScheme(); - if (Util.isLocalFileUri(dataSpec.uri)) { - String uriPath = dataSpec.uri.getPath(); + String scheme = uri.getScheme(); + if (Util.isLocalFileUri(uri)) { + String uriPath = uri.getPath(); if (uriPath != null && uriPath.startsWith("/android_asset/")) { dataSource = getAssetDataSource(); } else { - if (dataSpec.uri.getPath().endsWith(".enc")) { + if (uri.getPath().endsWith(".enc")) { dataSource = getEncryptedFileDataSource(); } else { dataSource = getFileDataSource(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSourceFactory.java b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSourceFactory.java index 4a7cffc2d0..a9f0bf3386 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSourceFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSourceFactory.java @@ -9,6 +9,8 @@ package org.telegram.messenger.secretmedia; import android.content.Context; +import android.net.Uri; +import android.util.LongSparseArray; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultDataSource; @@ -53,8 +55,15 @@ public ExtendedDefaultDataSourceFactory(Context context, TransferListener listen this.baseDataSourceFactory = baseDataSourceFactory; } + private final LongSparseArray mtprotoUris = new LongSparseArray<>(); + @Override public ExtendedDefaultDataSource createDataSource() { - return new ExtendedDefaultDataSource(context, listener, baseDataSourceFactory.createDataSource()); + return new ExtendedDefaultDataSource(context, listener, baseDataSourceFactory.createDataSource(), mtprotoUris); + } + + public void putDocumentUri(long docId, Uri uri) { + mtprotoUris.put(docId, uri); } + } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java index c95deca6fd..5ca7d06e62 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java @@ -267,6 +267,7 @@ public TLRPC.PhoneCall getPrivateCall() { private int scheduleDate; private TLRPC.InputPeer groupCallPeer; public boolean hasFewPeers; + public boolean isRtmpStream; private String joinHash; private int remoteVideoState = Instance.VIDEO_STATE_INACTIVE; @@ -714,6 +715,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { long chatID = intent.getLongExtra("chat_id", 0); createGroupCall = intent.getBooleanExtra("createGroupCall", false); hasFewPeers = intent.getBooleanExtra("hasFewPeers", false); + isRtmpStream = intent.getBooleanExtra("isRtmpStream", false); joinHash = intent.getStringExtra("hash"); long peerChannelId = intent.getLongExtra("peerChannelId", 0); long peerChatId = intent.getLongExtra("peerChatId", 0); @@ -1766,6 +1768,7 @@ private void startGroupCall(int ssrc, String json, boolean create) { groupCall.call.version = 1; groupCall.call.can_start_video = true; groupCall.call.can_change_join_muted = true; + groupCall.call.rtmp_stream = isRtmpStream; groupCall.chatId = chat.id; groupCall.currentAccount = AccountInstance.getInstance(currentAccount); groupCall.setSelfPeer(groupCallPeer); @@ -1779,6 +1782,9 @@ private void startGroupCall(int ssrc, String json, boolean create) { req.schedule_date = scheduleDate; req.flags |= 2; } + if (isRtmpStream) { + req.flags |= 4; + } groupCallBottomSheetLatch = new CountDownLatch(1); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index 859cfcb2d8..729639de4c 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -7,14 +7,9 @@ import android.os.AsyncTask; import android.os.Build; import android.os.SystemClock; -import android.text.SpannableString; -import android.text.Spanned; import android.text.TextUtils; import android.util.Base64; -import android.util.LongSparseArray; -import android.util.SparseIntArray; -import com.google.android.exoplayer2.util.Log; import com.google.android.gms.tasks.Task; import com.google.android.play.core.integrity.IntegrityManager; import com.google.android.play.core.integrity.IntegrityManagerFactory; @@ -39,20 +34,11 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.PushListenerController; -import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.StatsController; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; -import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ChatActivity; -import org.telegram.ui.Components.BulletinFactory; -import org.telegram.ui.Components.TypefaceSpan; -import org.telegram.ui.DialogsActivity; -import org.telegram.ui.LaunchActivity; import org.telegram.ui.LoginActivity; -import org.telegram.ui.PremiumPreviewFragment; import java.io.ByteArrayOutputStream; import java.io.File; @@ -364,14 +350,15 @@ private void sendRequestInternal(TLObject object, RequestDelegate onComplete, Re startRequestTime = System.currentTimeMillis(); } long finalStartRequestTime = startRequestTime; - listen(requestToken, (response, errorCode, errorText, networkType, timestamp, requestMsgId) -> { + listen(requestToken, (response, errorCode, errorText, networkType, timestamp, requestMsgId, dcId) -> { try { TLObject resp = null; TLRPC.TL_error error = null; - + int responseSize = 0; if (response != 0) { NativeByteBuffer buff = NativeByteBuffer.wrap(response); buff.reused = true; + responseSize = buff.limit(); int magic = buff.readInt32(true); try { resp = object.deserializeResponse(buff, magic, true); @@ -475,14 +462,14 @@ public static void onRequestClear(int currentAccount, int requestToken, boolean } } - public static void onRequestComplete(int currentAccount, int requestToken, long response, int errorCode, String errorText, int networkType, long timestamp, long requestMsgId) { + public static void onRequestComplete(int currentAccount, int requestToken, long response, int errorCode, String errorText, int networkType, long timestamp, long requestMsgId, int dcId) { ConnectionsManager connectionsManager = getInstance(currentAccount); if (connectionsManager == null) return; RequestCallbacks callbacks = connectionsManager.requestCallbacks.get(requestToken); connectionsManager.requestCallbacks.remove(requestToken); if (callbacks != null) { if (callbacks.onComplete != null) { - callbacks.onComplete.run(response, errorCode, errorText, networkType, timestamp, requestMsgId); + callbacks.onComplete.run(response, errorCode, errorText, networkType, timestamp, requestMsgId, dcId); } FileLog.d("{rc} onRequestComplete(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks"); } else { @@ -1477,7 +1464,7 @@ public static void onPremiumFloodWait(final int currentAccount, final int reques if (UserConfig.selectedAccount != currentAccount) { return; } - FileLoader.getInstance(currentAccount).getFileLoaderQueue().postRunnable(() -> { + AndroidUtilities.runOnUIThread(() -> { boolean updated = false; if (isUpload) { FileUploadOperation operation = FileLoader.getInstance(currentAccount).findUploadOperationByRequestToken(requestToken); @@ -1493,11 +1480,9 @@ public static void onPremiumFloodWait(final int currentAccount, final int reques } } final boolean finalUpdated = updated; - AndroidUtilities.runOnUIThread(() -> { - if (finalUpdated) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.premiumFloodWaitReceived); - } - }); + if (finalUpdated) { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.premiumFloodWaitReceived); + } }); }); } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/RequestDelegateInternal.java b/TMessagesProj/src/main/java/org/telegram/tgnet/RequestDelegateInternal.java index 62d501eb81..e6af78e6fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/RequestDelegateInternal.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/RequestDelegateInternal.java @@ -1,5 +1,5 @@ package org.telegram.tgnet; public interface RequestDelegateInternal { - void run(long response, int errorCode, String errorText, int networkType, long timestamp, long requestMsgId); + void run(long response, int errorCode, String errorText, int networkType, long timestamp, long requestMsgId, int dcId); } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index df98e9280b..31d62588bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -28,6 +28,7 @@ import org.telegram.messenger.SvgHelper; import org.telegram.messenger.Utilities; import org.telegram.tgnet.tl.TL_bots; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stats; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Stories.MessageMediaStoryFull; @@ -80,7 +81,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 = 187; + public static final int LAYER = 191; public static abstract class EmailVerifyPurpose extends TLObject { @@ -1749,6 +1750,7 @@ public static abstract class DocumentAttribute extends TLObject { public int preload_prefix_size; public double video_start_ts; public boolean nosound; + public String video_codec; public static DocumentAttribute TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { DocumentAttribute result = null; @@ -1774,6 +1776,9 @@ public static DocumentAttribute TLdeserialize(AbstractSerializedData stream, int case TL_documentAttributeVideo.constructor: result = new TL_documentAttributeVideo(); break; + case TL_documentAttributeVideo_layer187.constructor: + result = new TL_documentAttributeVideo_layer187(); + break; case TL_documentAttributeVideo_layer184.constructor: result = new TL_documentAttributeVideo_layer184(); break; @@ -1892,6 +1897,49 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_documentAttributeVideo extends DocumentAttribute { + public static final int constructor = 0x43c57c48; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + round_message = (flags & 1) != 0; + supports_streaming = (flags & 2) != 0; + nosound = (flags & 8) != 0; + duration = stream.readDouble(exception); + w = stream.readInt32(exception); + h = stream.readInt32(exception); + if ((flags & 4) != 0) { + preload_prefix_size = stream.readInt32(exception); + } + if ((flags & 16) != 0) { + video_start_ts = stream.readDouble(exception); + } + if ((flags & 32) != 0) { + video_codec = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = round_message ? (flags | 1) : (flags &~ 1); + flags = supports_streaming ? (flags | 2) : (flags &~ 2); + flags = nosound ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeDouble(duration); + stream.writeInt32(w); + stream.writeInt32(h); + if ((flags & 4) != 0) { + stream.writeInt32(preload_prefix_size); + } + if ((flags & 16) != 0) { + stream.writeDouble(video_start_ts); + } + if ((flags & 32) != 0) { + stream.writeString(video_codec); + } + } + } + + public static class TL_documentAttributeVideo_layer187 extends TL_documentAttributeVideo { public static final int constructor = 0x17399fad; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -3715,6 +3763,9 @@ public static PaymentForm TLdeserialize(AbstractSerializedData stream, int const case TL_payments_paymentFormStars.constructor: result = new TL_payments_paymentFormStars(); break; + case TL_payments_paymentFormStarGift.constructor: + result = new TL_payments_paymentFormStarGift(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in PaymentForm", constructor)); @@ -3906,6 +3957,21 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_payments_paymentFormStarGift extends PaymentForm { + public static final int constructor = 0xb425cfe1; + + public void readParams(AbstractSerializedData stream, boolean exception) { + form_id = stream.readInt64(exception); + invoice = TL_invoice.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(form_id); + invoice.serializeToStream(stream); + } + } + public static class TL_paymentFormMethod extends TLObject { public static final int constructor = 0x88f8f21b; @@ -6092,7 +6158,7 @@ public static abstract class ChatInvite extends TLObject { public boolean fake; public boolean can_refulfill_subscription; public int color; - public TL_starsSubscriptionPricing subscription_pricing; + public TL_stars.TL_starsSubscriptionPricing subscription_pricing; public long subscription_form_id; public static ChatInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -6164,7 +6230,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } color = stream.readInt32(exception); if ((flags & 1024) != 0) { - subscription_pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); + subscription_pricing = TL_stars.TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 4096) != 0) { subscription_form_id = stream.readInt64(exception); @@ -8720,6 +8786,65 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messageMediaDocument extends MessageMedia { + public static final int constructor = 0xdd570bd5; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + nopremium = (flags & 8) != 0; + spoiler = (flags & 16) != 0; + video = (flags & 64) != 0; + round = (flags & 128) != 0; + voice = (flags & 256) != 0; + if ((flags & 1) != 0) { + document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 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; + } + alt_documents.add(object); + } + } + if ((flags & 4) != 0) { + ttl_seconds = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = nopremium ? (flags | 8) : (flags &~ 8); + flags = spoiler ? (flags | 16) : (flags &~ 16); + flags = video ? (flags | 64) : (flags &~ 64); + flags = round ? (flags | 128) : (flags &~ 128); + flags = voice ? (flags | 256) : (flags &~ 256); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + document.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeInt32(0x1cb5c415); + stream.writeInt32(alt_documents.size()); + for (int i = 0; i < alt_documents.size(); ++i) { + alt_documents.get(i).serializeToStream(stream); + } + } + if ((flags & 4) != 0) { + stream.writeInt32(ttl_seconds); + } + } + } + + public static class TL_messageMediaDocument_layer187 extends TL_messageMediaDocument { public static final int constructor = 0x4cf4d72d; @@ -8734,7 +8859,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 32) != 0) { - alt_document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + alt_documents.add(Document.TLdeserialize(stream, stream.readInt32(exception), exception)); } if ((flags & 4) != 0) { ttl_seconds = stream.readInt32(exception); @@ -8753,7 +8878,7 @@ public void serializeToStream(AbstractSerializedData stream) { document.serializeToStream(stream); } if ((flags & 32) != 0) { - alt_document.serializeToStream(stream); + alt_documents.get(0).serializeToStream(stream); } if ((flags & 4) != 0) { stream.writeInt32(ttl_seconds); @@ -21002,6 +21127,9 @@ public static KeyboardButton TLdeserialize(AbstractSerializedData stream, int co case TL_keyboardButtonRequestPeer.constructor: result = new TL_keyboardButtonRequestPeer(); break; + case TL_keyboardButtonCopy.constructor: + result = new TL_keyboardButtonCopy(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in KeyboardButton", constructor)); @@ -28009,34 +28137,37 @@ public static MessageAction TLdeserialize(AbstractSerializedData stream, int con case TL_messageActionGiftCode.constructor: result = new TL_messageActionGiftCode(); break; + case TL_messageActionGiftCode_layer189.constructor: + result = new TL_messageActionGiftCode_layer189(); + break; case TL_messageActionGiftCode_layer167.constructor: result = new TL_messageActionGiftCode_layer167(); break; - case 0xb18a431c: + case TL_messageActionTopicEdit_layer149.constructor: result = new TL_messageActionTopicEdit_layer149(); break; - case 0xc0944820: + case TL_messageActionTopicEdit.constructor: result = new TL_messageActionTopicEdit(); break; - case 0x55555551: + case TL_messageActionUserUpdatedPhoto.constructor: result = new TL_messageActionUserUpdatedPhoto(); break; - case 0x5e3cfc4b: + case TL_messageActionChatAddUser_old.constructor: result = new TL_messageActionChatAddUser_old(); break; - case 0x55555552: + case TL_messageActionTTLChange.constructor: result = new TL_messageActionTTLChange(); break; - case 0x3c134d7b: + case TL_messageActionSetMessagesTTL.constructor: result = new TL_messageActionSetMessagesTTL(); break; - case 0xaa1afbfd: + case TL_messageActionSetMessagesTTL_layer149.constructor: result = new TL_messageActionSetMessagesTTL_layer149(); break; - case 0xd95c6154: + case TL_messageActionSecureValuesSent.constructor: result = new TL_messageActionSecureValuesSent(); break; - case 0x47dd8079: + case TL_messageActionWebViewDataSentMe.constructor: result = new TL_messageActionWebViewDataSentMe(); break; case 0xb4c38cb5: @@ -28087,30 +28218,33 @@ public static MessageAction TLdeserialize(AbstractSerializedData stream, int con case 0xc516d679: result = new TL_messageActionBotAllowed(); break; - case 0x96163f56: + case TL_messageActionPaymentSent.constructor: result = new TL_messageActionPaymentSent(); break; - case 0x40699cd0: + case TL_messageActionPaymentSent_layer140.constructor: result = new TL_messageActionPaymentSent_layer140(); break; - case 0xb6aef7b0: + case TL_messageActionEmpty.constructor: result = new TL_messageActionEmpty(); break; - case 0x92a72876: + case TL_messageActionGameScore.constructor: result = new TL_messageActionGameScore(); break; - case 0xb3a07661: + case TL_messageActionGroupCallScheduled.constructor: result = new TL_messageActionGroupCallScheduled(); break; case TL_messageActionBoostApply.constructor: result = new TL_messageActionBoostApply(); break; - case 0x8f31b327: + case TL_messageActionPaymentSentMe.constructor: result = new TL_messageActionPaymentSentMe(); break; - case 0xc83d6aec: + case TL_messageActionGiftPremium.constructor: result = new TL_messageActionGiftPremium(); break; + case TL_messageActionGiftPremium_layer189.constructor: + result = new TL_messageActionGiftPremium_layer189(); + break; case TL_messageActionRequestedPeer_layer168.constructor: result = new TL_messageActionRequestedPeer_layer168(); break; @@ -28126,6 +28260,9 @@ public static MessageAction TLdeserialize(AbstractSerializedData stream, int con case TL_messageActionPrizeStars.constructor: result = new TL_messageActionPrizeStars(); break; + case TL_messageActionStarGift.constructor: + result = new TL_messageActionStarGift(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in MessageAction", constructor)); @@ -29213,6 +29350,41 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messageActionGiftPremium extends MessageAction { + public static final int constructor = 0x6c6274fa; + + public TL_textWithEntities message; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + currency = stream.readString(exception); + amount = stream.readInt64(exception); + months = stream.readInt32(exception); + if ((flags & 1) != 0) { + cryptoCurrency = stream.readString(exception); + cryptoAmount = stream.readInt64(exception); + } + if ((flags & 2) != 0) { + message = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeString(currency); + stream.writeInt64(amount); + stream.writeInt32(months); + if ((flags & 1) != 0) { + stream.writeString(cryptoCurrency); + stream.writeInt64(cryptoAmount); + } + if ((flags & 2) != 0) { + message.serializeToStream(stream); + } + } + } + + public static class TL_messageActionGiftPremium_layer189 extends TL_messageActionGiftPremium { public static final int constructor = 0xc83d6aec; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -53376,7 +53548,7 @@ public static class TL_chatInviteExported extends ExportedChatInvite { public int requested; public int subscription_expired; public String title; - public TL_starsSubscriptionPricing subscription_pricing; + public TL_stars.TL_starsSubscriptionPricing subscription_pricing; public ArrayList importers; //custom public boolean expired; //custom @@ -53410,7 +53582,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { title = stream.readString(exception); } if ((flags & 512) != 0) { - subscription_pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); + subscription_pricing = TL_stars.TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -54034,6 +54206,7 @@ public static abstract class UserFull extends TLObject { public TL_birthday birthday; public long personal_channel_id; public int personal_channel_message; + public int stargifts_count; public static UserFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { UserFull result = null; @@ -54041,6 +54214,9 @@ public static UserFull TLdeserialize(AbstractSerializedData stream, int construc case TL_userFull.constructor: result = new TL_userFull(); break; + case TL_userFull_layer188.constructor: + result = new TL_userFull_layer188(); + break; case TL_userFull_layer176_3.constructor: result = new TL_userFull_layer176_3(); break; @@ -54101,7 +54277,7 @@ public static UserFull TLdeserialize(AbstractSerializedData stream, int construc } public static class TL_userFull extends UserFull { - public static final int constructor = 0xcc997720; + public static final int constructor = 0x1f58e369; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -54205,6 +54381,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { personal_channel_id = stream.readInt64(exception); personal_channel_message = stream.readInt32(exception); } + if ((flags2 & 256) != 0) { + stargifts_count = stream.readInt32(exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -54301,11 +54480,14 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt64(personal_channel_id); stream.writeInt32(personal_channel_message); } + if ((flags2 & 256) != 0) { + stream.writeInt32(stargifts_count); + } } } - public static class TL_userFull_layer176_3 extends TL_userFull { - public static final int constructor = 0xecdadceb; + public static class TL_userFull_layer188 extends TL_userFull { + public static final int constructor = 0xcc997720; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -54323,6 +54505,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { 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); @@ -54404,6 +54587,10 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags2 & 32) != 0) { birthday = TL_birthday.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 64) != 0) { + personal_channel_id = stream.readInt64(exception); + personal_channel_message = stream.readInt32(exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -54422,6 +54609,7 @@ public void serializeToStream(AbstractSerializedData stream) { 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) { @@ -54495,11 +54683,15 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags2 & 32) != 0) { birthday.serializeToStream(stream); } + if ((flags2 & 64) != 0) { + stream.writeInt64(personal_channel_id); + stream.writeInt32(personal_channel_message); + } } } - public static class TL_userFull_layer176_2 extends TL_userFull { - public static final int constructor = 0x670bbc9c; + public static class TL_userFull_layer176_3 extends TL_userFull { + public static final int constructor = 0xecdadceb; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -54595,6 +54787,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags2 & 16) != 0) { business_intro = TL_businessIntro.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 32) != 0) { + birthday = TL_birthday.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -54683,11 +54878,14 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags2 & 16) != 0) { business_intro.serializeToStream(stream); } + if ((flags2 & 32) != 0) { + birthday.serializeToStream(stream); + } } } - public static class TL_userFull_layer176 extends TL_userFull { - public static final int constructor = 0x22ff3e85; + public static class TL_userFull_layer176_2 extends TL_userFull { + public static final int constructor = 0x670bbc9c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -54780,6 +54978,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags2 & 8) != 0) { business_away_message = TL_businessAwayMessage.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 16) != 0) { + business_intro = TL_businessIntro.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -54865,10 +55066,14 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags2 & 8) != 0) { business_away_message.serializeToStream(stream); } + if ((flags2 & 16) != 0) { + business_intro.serializeToStream(stream); + } } } - public static class TL_userFull_layer175 extends TL_userFull { - public static final int constructor = 0xb9b12c6c; + + public static class TL_userFull_layer176 extends TL_userFull { + public static final int constructor = 0x22ff3e85; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -54885,6 +55090,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { wallpaper_overridden = (flags & 268435456) != 0; contact_require_premium = (flags & 536870912) != 0; read_dates_private = (flags & 1073741824) != 0; + flags2 = stream.readInt32(exception); id = stream.readInt64(exception); if ((flags & 2) != 0) { about = stream.readString(exception); @@ -54948,6 +55154,18 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 33554432) != 0) { stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 1) != 0) { + business_work_hours = TL_businessWorkHours.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 2) != 0) { + business_location = TL_businessLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 4) != 0) { + business_greeting_message = TL_businessGreetingMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 8) != 0) { + business_away_message = TL_businessAwayMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -54966,6 +55184,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = contact_require_premium ? (flags | 536870912) : (flags &~ 536870912); flags = read_dates_private ? (flags | 1073741824) : (flags &~ 1073741824); stream.writeInt32(flags); + stream.writeInt32(flags2); stream.writeInt64(id); if ((flags & 2) != 0) { stream.writeString(about); @@ -55020,11 +55239,22 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 33554432) != 0) { stories.serializeToStream(stream); } + if ((flags2 & 1) != 0) { + business_work_hours.serializeToStream(stream); + } + if ((flags2 & 2) != 0) { + business_location.serializeToStream(stream); + } + if ((flags2 & 4) != 0) { + business_greeting_message.serializeToStream(stream); + } + if ((flags2 & 8) != 0) { + business_away_message.serializeToStream(stream); + } } } - - public static class TL_userFull_layer162 extends UserFull { - public static final int constructor = 0x4fe1cc86; + public static class TL_userFull_layer175 extends TL_userFull { + public static final int constructor = 0xb9b12c6c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -55038,6 +55268,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { translations_disabled = (flags & 8388608) != 0; stories_pinned_available = (flags & 67108864) != 0; blocked_my_stories_from = (flags & 134217728) != 0; + wallpaper_overridden = (flags & 268435456) != 0; + contact_require_premium = (flags & 536870912) != 0; + read_dates_private = (flags & 1073741824) != 0; id = stream.readInt64(exception); if ((flags & 2) != 0) { about = stream.readString(exception); @@ -55115,6 +55348,9 @@ public void serializeToStream(AbstractSerializedData stream) { flags = translations_disabled ? (flags | 8388608) : (flags &~ 8388608); flags = stories_pinned_available ? (flags | 67108864) : (flags &~ 67108864); flags = blocked_my_stories_from ? (flags | 134217728) : (flags &~ 134217728); + flags = wallpaper_overridden ? (flags | 268435456) : (flags &~ 268435456); + flags = contact_require_premium ? (flags | 536870912) : (flags &~ 536870912); + flags = read_dates_private ? (flags | 1073741824) : (flags &~ 1073741824); stream.writeInt32(flags); stream.writeInt64(id); if ((flags & 2) != 0) { @@ -55173,8 +55409,8 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_userFull_layer159 extends UserFull { - public static final int constructor = 0x93eadb53; + public static class TL_userFull_layer162 extends UserFull { + public static final int constructor = 0x4fe1cc86; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -55186,6 +55422,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { video_calls_available = (flags & 8192) != 0; voice_messages_forbidden = (flags & 1048576) != 0; translations_disabled = (flags & 8388608) != 0; + stories_pinned_available = (flags & 67108864) != 0; + blocked_my_stories_from = (flags & 134217728) != 0; id = stream.readInt64(exception); if ((flags & 2) != 0) { about = stream.readString(exception); @@ -55246,6 +55484,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 16777216) != 0) { wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 33554432) != 0) { + stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -55258,6 +55499,8 @@ public void serializeToStream(AbstractSerializedData stream) { flags = video_calls_available ? (flags | 8192) : (flags &~ 8192); flags = voice_messages_forbidden ? (flags | 1048576) : (flags &~ 1048576); flags = translations_disabled ? (flags | 8388608) : (flags &~ 8388608); + flags = stories_pinned_available ? (flags | 67108864) : (flags &~ 67108864); + flags = blocked_my_stories_from ? (flags | 134217728) : (flags &~ 134217728); stream.writeInt32(flags); stream.writeInt64(id); if ((flags & 2) != 0) { @@ -55310,11 +55553,14 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 16777216) != 0) { wallpaper.serializeToStream(stream); } + if ((flags & 33554432) != 0) { + stories.serializeToStream(stream); + } } } - public static class TL_userFull_layer156 extends UserFull { - public static final int constructor = 0xf8d32aed; + public static class TL_userFull_layer159 extends UserFull { + public static final int constructor = 0x93eadb53; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -55383,6 +55629,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { premium_gifts.add(object); } } + if ((flags & 16777216) != 0) { + wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -55444,11 +55693,148 @@ public void serializeToStream(AbstractSerializedData stream) { premium_gifts.get(a).serializeToStream(stream); } } + if ((flags & 16777216) != 0) { + wallpaper.serializeToStream(stream); + } } } - public static class TL_userFull_layer150_rev2 extends UserFull { - public static final int constructor = 0xec6d41e3; + public static class TL_userFull_layer156 extends UserFull { + public static final int constructor = 0xf8d32aed; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + blocked = (flags & 1) != 0; + phone_calls_available = (flags & 16) != 0; + phone_calls_private = (flags & 32) != 0; + can_pin_message = (flags & 128) != 0; + has_scheduled = (flags & 4096) != 0; + video_calls_available = (flags & 8192) != 0; + voice_messages_forbidden = (flags & 1048576) != 0; + translations_disabled = (flags & 8388608) != 0; + id = stream.readInt64(exception); + if ((flags & 2) != 0) { + about = stream.readString(exception); + } + settings = PeerSettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 2097152) != 0) { + personal_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 4) != 0) { + profile_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 4194304) != 0) { + fallback_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8) != 0) { + bot_info = TL_bots.BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 64) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + common_chats_count = stream.readInt32(exception); + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + if ((flags & 16384) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + theme_emoticon = stream.readString(exception); + } + if ((flags & 65536) != 0) { + private_forward_name = stream.readString(exception); + } + if ((flags & 131072) != 0) { + bot_group_admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 262144) != 0) { + bot_broadcast_admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 524288) != 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++) { + TL_premiumGiftOption object = TL_premiumGiftOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + premium_gifts.add(object); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = blocked ? (flags | 1) : (flags &~ 1); + flags = phone_calls_available ? (flags | 16) : (flags &~ 16); + flags = phone_calls_private ? (flags | 32) : (flags &~ 32); + flags = can_pin_message ? (flags | 128) : (flags &~ 128); + flags = has_scheduled ? (flags | 4096) : (flags &~ 4096); + flags = video_calls_available ? (flags | 8192) : (flags &~ 8192); + flags = voice_messages_forbidden ? (flags | 1048576) : (flags &~ 1048576); + flags = translations_disabled ? (flags | 8388608) : (flags &~ 8388608); + stream.writeInt32(flags); + stream.writeInt64(id); + if ((flags & 2) != 0) { + stream.writeString(about); + } + settings.serializeToStream(stream); + if ((flags & 2097152) != 0) { + personal_photo.serializeToStream(stream); + } + if ((flags & 4) != 0) { + profile_photo.serializeToStream(stream); + } + if ((flags & 4194304) != 0) { + fallback_photo.serializeToStream(stream); + } + notify_settings.serializeToStream(stream); + if ((flags & 8) != 0) { + bot_info.serializeToStream(stream); + } + if ((flags & 64) != 0) { + stream.writeInt32(pinned_msg_id); + } + stream.writeInt32(common_chats_count); + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + if ((flags & 16384) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 32768) != 0) { + stream.writeString(theme_emoticon); + } + if ((flags & 65536) != 0) { + stream.writeString(private_forward_name); + } + if ((flags & 131072) != 0) { + bot_group_admin_rights.serializeToStream(stream); + } + if ((flags & 262144) != 0) { + bot_broadcast_admin_rights.serializeToStream(stream); + } + if ((flags & 524288) != 0) { + stream.writeInt32(0x1cb5c415); + int count = premium_gifts.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + premium_gifts.get(a).serializeToStream(stream); + } + } + } + } + + public static class TL_userFull_layer150_rev2 extends UserFull { + public static final int constructor = 0xec6d41e3; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -60793,16 +61179,146 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messageReportOption extends TLObject { + public static final int constructor = 0x7903e3d9; + + public String text; + public byte[] option; + + public static TL_messageReportOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messageReportOption.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messageReportOption", constructor)); + } else { + return null; + } + } + TL_messageReportOption result = new TL_messageReportOption(); + result.readParams(stream, exception); + return result; + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + text = stream.readString(exception); + option = stream.readByteArray(exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(text); + stream.writeByteArray(option); + } + } + + public static class ReportResult extends TLObject { + public static ReportResult TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + ReportResult result = null; + switch (constructor) { + case TL_reportResultChooseOption.constructor: + result = new TL_reportResultChooseOption(); + break; + case TL_reportResultAddComment.constructor: + result = new TL_reportResultAddComment(); + break; + case TL_reportResultReported.constructor: + result = new TL_reportResultReported(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in ReportResult", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_reportResultChooseOption extends ReportResult { + public static final int constructor = 0xf0e4e0b6; + + public String title; + public ArrayList options = new ArrayList<>(); + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + title = 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++) { + TL_messageReportOption object = TL_messageReportOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + options.add(object); + } + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(title); + stream.writeInt32(0x1cb5c415); + stream.writeInt32(options.size()); + for (int i = 0; i < options.size(); ++i) { + options.get(i).serializeToStream(stream); + } + } + } + + public static class TL_reportResultAddComment extends ReportResult { + public static final int constructor = 0x6f09ac31; + + public int flags; + public boolean optional; + public byte[] option; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + optional = (flags & 1) != 0; + option = stream.readByteArray(exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = optional ? flags | 1 : flags &~ 1; + stream.writeInt32(flags); + stream.writeByteArray(option); + } + } + + public static class TL_reportResultReported extends ReportResult { + public static final int constructor = 0x8db33c4b; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) {} + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_messages_report extends TLObject { - public static final int constructor = 0x8953ab4e; + public static final int constructor = 0xfc78af9b; public InputPeer peer; public ArrayList id = new ArrayList<>(); - public ReportReason reason; + public byte[] option; public String message; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); + return ReportResult.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -60814,7 +61330,7 @@ public void serializeToStream(AbstractSerializedData stream) { for (int a = 0; a < count; a++) { stream.writeInt32(id.get(a)); } - reason.serializeToStream(stream); + stream.writeByteArray(option); stream.writeString(message); } } @@ -62744,7 +63260,7 @@ public static class TL_messages_exportChatInvite extends TLObject { public int expire_date; public int usage_limit; public String title; - public TL_starsSubscriptionPricing subscription_pricing; + public TL_stars.TL_starsSubscriptionPricing subscription_pricing; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return ExportedChatInvite.TLdeserialize(stream, constructor, exception); @@ -68041,7 +68557,7 @@ public static abstract class MessageMedia extends TLObject { public String venue_id; public Video video_unused; public Document document; - public Document alt_document; + public ArrayList alt_documents = new ArrayList<>(); public String captionLegacy; public TL_game game; public String phone_number; @@ -68186,9 +68702,12 @@ public static MessageMedia TLdeserialize(AbstractSerializedData stream, int cons case 0xddf10c3b: result = new TL_messageMediaWebPage(); break; - case 0x4cf4d72d: + case TL_messageMediaDocument.constructor: result = new TL_messageMediaDocument(); break; + case TL_messageMediaDocument_layer187.constructor: + result = new TL_messageMediaDocument_layer187(); + break; case 0x9cb070d7: result = new TL_messageMediaDocument_layer159(); break; @@ -68275,8 +68794,8 @@ public static MessageMedia TLdeserialize(AbstractSerializedData stream, int cons } public Document getDocument() { - if (alt_document != null && !MessagesController.isStoryQualityFull()) { - return alt_document; + if (!alt_documents.isEmpty() && !MessagesController.isStoryQualityFull()) { + return alt_documents.get(0); } return document; } @@ -74524,6 +75043,23 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_keyboardButtonCopy extends KeyboardButton { + public static final int constructor = 0x75d2698e; + + public String copy_text; + + public void readParams(AbstractSerializedData stream, boolean exception) { + text = stream.readString(exception); + copy_text = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(text); + stream.writeString(copy_text); + } + } + public static class TL_messages_getAttachMenuBots extends TLObject { public static final int constructor = 0x16fcc2cb; @@ -75636,13 +76172,13 @@ public static abstract class InputInvoice extends TLObject { public static InputInvoice TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { InputInvoice result = null; switch (constructor) { - case 0x98986c0d: + case TL_inputInvoicePremiumGiftCode.constructor: result = new TL_inputInvoicePremiumGiftCode(); break; - case 0xc5b56859: + case TL_inputInvoiceMessage.constructor: result = new TL_inputInvoiceMessage(); break; - case 0xc326caef: + case TL_inputInvoiceSlug.constructor: result = new TL_inputInvoiceSlug(); break; case TL_inputInvoiceStars.constructor: @@ -75651,6 +76187,9 @@ public static InputInvoice TLdeserialize(AbstractSerializedData stream, int cons case TL_inputInvoiceChatInviteSubscription.constructor: result = new TL_inputInvoiceChatInviteSubscription(); break; + case TL_inputInvoiceStarGift.constructor: + result = new TL_inputInvoiceStarGift(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in InputInvoice", constructor)); @@ -76876,8 +77415,11 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_channels_clickSponsoredMessage extends TLObject { - public static final int constructor = 0x18afbc93; + public static final int constructor = 0x1445d75; + public int flags; + public boolean media; + public boolean fullscreen; public InputChannel channel; public byte[] random_id; @@ -76887,6 +77429,9 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = media ? flags | 1 : flags &~ 1; + flags = fullscreen ? flags | 2 : flags &~ 2; + stream.writeInt32(flags); channel.serializeToStream(stream); stream.writeByteArray(random_id); } @@ -78004,6 +78549,61 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messageActionGiftCode extends MessageAction { + public static final int constructor = 0x56d03994; + + public boolean via_giveaway; + public boolean unclaimed; + public Peer boost_peer; + public String slug; + public TL_textWithEntities message; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + via_giveaway = (flags & 1) != 0; + unclaimed = (flags & 4) != 0; + if ((flags & 2) != 0) { + boost_peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + months = stream.readInt32(exception); + slug = stream.readString(exception); + if ((flags & 4) != 0) { + currency = stream.readString(exception); + amount = stream.readInt64(exception); + } + if ((flags & 8) != 0) { + cryptoCurrency = stream.readString(exception); + cryptoAmount = stream.readInt64(exception); + } + if ((flags & 16) != 0) { + message = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = via_giveaway ? (flags | 1) : (flags &~ 1); + flags = unclaimed ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + if ((flags & 2) != 0) { + boost_peer.serializeToStream(stream); + } + stream.writeInt32(months); + stream.writeString(slug); + if ((flags & 4) != 0) { + stream.writeString(currency); + stream.writeInt64(amount); + } + if ((flags & 8) != 0) { + stream.writeString(cryptoCurrency); + stream.writeInt64(cryptoAmount); + } + if ((flags & 16) != 0) { + message.serializeToStream(stream); + } + } + } + + public static class TL_messageActionGiftCode_layer189 extends TL_messageActionGiftCode { public static final int constructor = 0x678c2e09; public boolean via_giveaway; @@ -78087,13 +78687,14 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_inputStorePaymentPremiumGiftCode extends InputStorePaymentPurpose { - public static final int constructor = 0xa3805f3f; + public static final int constructor = 0xfb790393; public int flags; public ArrayList users = new ArrayList<>(); public InputPeer boost_peer; public String currency; public long amount; + public TL_textWithEntities message; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -78117,6 +78718,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } currency = stream.readString(exception); amount = stream.readInt64(exception); + if ((flags & 2) != 0) { + message = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -78133,6 +78737,9 @@ public void serializeToStream(AbstractSerializedData stream) { } stream.writeString(currency); stream.writeInt64(amount); + if ((flags & 2) != 0) { + message.serializeToStream(stream); + } } } @@ -78417,6 +79024,37 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_inputInvoiceStarGift extends InputInvoice { + public static final int constructor = 0x25d8c1d8; + + public int flags; + public boolean hide_name; + public InputPeer user_id; + public long gift_id; + public TL_textWithEntities message; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + hide_name = (flags & 1) != 0; + user_id = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + gift_id = stream.readInt64(exception); + if ((flags & 2) != 0) { + message = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = hide_name ? flags | 1 : flags &~ 1; + stream.writeInt32(flags); + user_id.serializeToStream(stream); + stream.writeInt64(gift_id); + if ((flags & 2) != 0) { + message.serializeToStream(stream); + } + } + } + public static class TL_messageMediaGiveawayResults extends MessageMedia { public static final int constructor = 0xceaa3ea1; @@ -79307,8 +79945,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(flags); flags = unclaimed ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); stream.writeInt64(stars); stream.writeString(transaction_id); boost_peer.serializeToStream(stream); @@ -79316,6 +79954,46 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messageActionStarGift extends MessageAction { + public static final int constructor = 0x9bb3ef44; + + public int flags; + public boolean name_hidden; + public boolean saved; + public boolean converted; + public TL_stars.StarGift gift; + public TL_textWithEntities message; + public long convert_stars; + + public boolean forceIn; //custom + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + name_hidden = (flags & 1) != 0; + saved = (flags & 4) != 0; + converted = (flags & 8) != 0; + gift = TL_stars.StarGift.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 2) != 0) { + message = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); + } + convert_stars = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = name_hidden ? (flags | 1) : (flags &~ 1); + flags = saved ? (flags | 4) : (flags &~ 4); + flags = converted ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + gift.serializeToStream(stream); + if ((flags & 2) != 0) { + message.serializeToStream(stream); + } + stream.writeInt64(convert_stars); + } + } + public static class TL_channels_updateEmojiStatus extends TLObject { public static final int constructor = 0xf0d3e6a8; @@ -82756,1052 +83434,6 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_starsTopupOption extends TLObject { - public static final int constructor = 0xbd915c0; - - public int flags; - public boolean extended; - public long stars; - public String store_product; - public String currency; - public long amount; - public boolean loadingStorePrice; //custom - public boolean missingStorePrice; //custom - - public static TL_starsTopupOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_starsTopupOption.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_starsTopupOption", constructor)); - } else { - return null; - } - } - TL_starsTopupOption result = new TL_starsTopupOption(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - extended = (flags & 2) != 0; - stars = stream.readInt64(exception); - if ((flags & 1) != 0) { - store_product = stream.readString(exception); - } - currency = stream.readString(exception); - amount = stream.readInt64(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = extended ? flags | 2 : flags &~ 2; - stream.writeInt32(flags); - stream.writeInt64(stars); - if ((flags & 1) != 0) { - stream.writeString(store_product); - } - stream.writeString(currency); - stream.writeInt64(amount); - } - } - - public static class TL_starsGiftOption extends TLObject { - public static final int constructor = 0x5e0589f1; - - public int flags; - public boolean extended; - public long stars; - public String store_product; - public String currency; - public long amount; - public boolean loadingStorePrice; //custom - public boolean missingStorePrice; //custom - - public static TL_starsGiftOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_starsGiftOption.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_starsGiftOption", constructor)); - } else { - return null; - } - } - TL_starsGiftOption result = new TL_starsGiftOption(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - extended = (flags & 2) != 0; - stars = stream.readInt64(exception); - if ((flags & 1) != 0) { - store_product = stream.readString(exception); - } - currency = stream.readString(exception); - amount = stream.readInt64(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = extended ? flags | 2 : flags &~ 2; - stream.writeInt32(flags); - stream.writeInt64(stars); - if ((flags & 1) != 0) { - stream.writeString(store_product); - } - stream.writeString(currency); - stream.writeInt64(amount); - } - } - - public static class TL_starsGiveawayWinnersOption extends TLObject { - public static final int constructor = 0x54236209; - - public int flags; - public boolean isDefault; - public int users; - public long per_user_stars; - - public static TL_starsGiveawayWinnersOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_starsGiveawayWinnersOption.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_starsGiveawayWinnersOption", constructor)); - } else { - return null; - } - } - TL_starsGiveawayWinnersOption result = new TL_starsGiveawayWinnersOption(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - isDefault = (flags & 1) != 0; - users = stream.readInt32(exception); - per_user_stars = stream.readInt64(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = isDefault ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - stream.writeInt32(users); - stream.writeInt64(per_user_stars); - } - } - - public static class TL_starsGiveawayOption extends TLObject { - public static final int constructor = 0x94ce852a; - - public int flags; - public boolean extended; - public boolean isDefault; - public long stars; - public int yearly_boosts; - public String store_product; - public String currency; - public long amount; - public ArrayList winners = new ArrayList<>(); - - public boolean loadingStorePrice; //custom - public boolean missingStorePrice; //custom - - public static TL_starsGiveawayOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_starsGiveawayOption.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_starsGiveawayOption", constructor)); - } else { - return null; - } - } - TL_starsGiveawayOption result = new TL_starsGiveawayOption(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - extended = (flags & 1) != 0; - isDefault = (flags & 2) != 0; - stars = stream.readInt64(exception); - yearly_boosts = stream.readInt32(exception); - if ((flags & 4) != 0) { - store_product = stream.readString(exception); - } - currency = stream.readString(exception); - amount = 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++) { - TL_starsGiveawayWinnersOption object = TL_starsGiveawayWinnersOption.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - winners.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = extended ? (flags | 1) : (flags &~ 1); - flags = isDefault ? (flags | 2) : (flags &~ 2); - stream.writeInt32(flags); - stream.writeInt64(stars); - stream.writeInt32(yearly_boosts); - if ((flags & 4) != 0) { - stream.writeString(store_product); - } - stream.writeString(currency); - stream.writeInt64(amount); - stream.writeInt32(0x1cb5c415); - int count = winners.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - winners.get(i).serializeToStream(stream); - } - } - } - - public static class StarsTransactionPeer extends TLObject { - - public Peer peer; - - public static StarsTransactionPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - StarsTransactionPeer result = null; - switch (constructor) { - case TL_starsTransactionPeer.constructor: - result = new TL_starsTransactionPeer(); - break; - case TL_starsTransactionPeerAppStore.constructor: - result = new TL_starsTransactionPeerAppStore(); - break; - case TL_starsTransactionPeerPlayMarket.constructor: - result = new TL_starsTransactionPeerPlayMarket(); - break; - case TL_starsTransactionPeerFragment.constructor: - result = new TL_starsTransactionPeerFragment(); - break; - case TL_starsTransactionPeerPremiumBot.constructor: - result = new TL_starsTransactionPeerPremiumBot(); - break; - case TL_starsTransactionPeerUnsupported.constructor: - result = new TL_starsTransactionPeerUnsupported(); - break; - case TL_starsTransactionPeerAds.constructor: - result = new TL_starsTransactionPeerAds(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in StarsTransactionPeer", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_starsTransactionPeer extends StarsTransactionPeer { - public static final int constructor = 0xd80da15d; - - public void readParams(AbstractSerializedData stream, boolean exception) { - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } - - public static class TL_starsTransactionPeerAppStore extends StarsTransactionPeer { - public static final int constructor = 0xb457b375; - - public void readParams(AbstractSerializedData stream, boolean exception) {} - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_starsTransactionPeerPlayMarket extends StarsTransactionPeer { - public static final int constructor = 0x7b560a0b; - - public void readParams(AbstractSerializedData stream, boolean exception) {} - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_starsTransactionPeerFragment extends StarsTransactionPeer { - public static final int constructor = 0xe92fd902; - - public void readParams(AbstractSerializedData stream, boolean exception) {} - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_starsTransactionPeerPremiumBot extends StarsTransactionPeer { - public static final int constructor = 0x250dbaf8; - - public void readParams(AbstractSerializedData stream, boolean exception) {} - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_starsTransactionPeerUnsupported extends StarsTransactionPeer { - public static final int constructor = 0x95f2bfe4; - - public void readParams(AbstractSerializedData stream, boolean exception) {} - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_starsTransactionPeerAds extends StarsTransactionPeer { - public static final int constructor = 0x60682812; - - public void readParams(AbstractSerializedData stream, boolean exception) {} - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class StarsTransaction extends TLObject { - - public int flags; - public boolean refund; - public boolean pending; - public boolean failed; - public boolean gift; - public boolean reaction; - public boolean subscription; - public String id; - public long stars; - public int date; - public StarsTransactionPeer peer; - public String title; - public String description; - public WebDocument photo; - public int transaction_date; - public String transaction_url; - public byte[] bot_payload; - public int msg_id; - public ArrayList extended_media = new ArrayList<>(); - public int subscription_period; - public int giveaway_post_id; - - public Peer sent_by; //custom - public Peer received_by; //custom - - public static StarsTransaction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - StarsTransaction result = null; - switch (constructor) { - case TL_starsTransaction_layer181.constructor: - result = new TL_starsTransaction_layer181(); - break; - case TL_starsTransaction_layer182.constructor: - result = new TL_starsTransaction_layer182(); - break; - case TL_starsTransaction_layer185.constructor: - result = new TL_starsTransaction_layer185(); - break; - case TL_starsTransaction_layer186.constructor: - result = new TL_starsTransaction_layer186(); - break; - case TL_starsTransaction.constructor: - result = new TL_starsTransaction(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in StarsTransaction", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - - } - - public static class TL_starsTransaction_layer181 extends StarsTransaction { - public static final int constructor = 0xcc7079b2; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - refund = (flags & 8) != 0; - id = stream.readString(exception); - stars = stream.readInt64(exception); - date = stream.readInt32(exception); - peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - title = stream.readString(exception); - } - if ((flags & 2) != 0) { - description = stream.readString(exception); - } - if ((flags & 4) != 0) { - photo = WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = refund ? flags | 8 : flags &~ 8; - stream.writeInt32(flags); - stream.writeInt64(stars); - stream.writeInt32(date); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeString(title); - } - if ((flags & 2) != 0) { - stream.writeString(description); - } - if ((flags & 4) != 0) { - photo.serializeToStream(stream); - } - } - } - - public static class TL_starsTransaction_layer182 extends TL_starsTransaction { - public static final int constructor = 0xaa00c898; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - refund = (flags & 8) != 0; - pending = (flags & 16) != 0; - failed = (flags & 64) != 0; - id = stream.readString(exception); - stars = stream.readInt64(exception); - date = stream.readInt32(exception); - peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - title = stream.readString(exception); - } - if ((flags & 2) != 0) { - description = stream.readString(exception); - } - if ((flags & 4) != 0) { - photo = WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 32) != 0) { - transaction_date = stream.readInt32(exception); - transaction_url = stream.readString(exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = refund ? flags | 8 : flags &~ 8; - flags = pending ? flags | 16 : flags &~ 16; - flags = failed ? flags | 64 : flags &~ 64; - stream.writeInt32(flags); - stream.writeInt64(stars); - stream.writeInt32(date); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeString(title); - } - if ((flags & 2) != 0) { - stream.writeString(description); - } - if ((flags & 4) != 0) { - photo.serializeToStream(stream); - } - if ((flags & 32) != 0) { - stream.writeInt32(transaction_date); - stream.writeString(transaction_url); - } - } - } - - public static class TL_starsTransaction extends StarsTransaction { - public static final int constructor = 0xee7522d5; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - refund = (flags & 8) != 0; - pending = (flags & 16) != 0; - failed = (flags & 64) != 0; - gift = (flags & 1024) != 0; - reaction = (flags & 2048) != 0; - subscription = (flags & 4096) != 0; - id = stream.readString(exception); - stars = stream.readInt64(exception); - date = stream.readInt32(exception); - peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - title = stream.readString(exception); - } - if ((flags & 2) != 0) { - description = stream.readString(exception); - } - if ((flags & 4) != 0) { - photo = WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 32) != 0) { - transaction_date = stream.readInt32(exception); - transaction_url = stream.readString(exception); - } - if ((flags & 128) != 0) { - bot_payload = stream.readByteArray(exception); - } - if ((flags & 256) != 0) { - msg_id = stream.readInt32(exception); - } - if ((flags & 512) != 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++) { - MessageMedia object = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - extended_media.add(object); - } - } - if ((flags & 4096) != 0) { - subscription_period = stream.readInt32(exception); - } - if ((flags & 8192) != 0) { - giveaway_post_id = stream.readInt32(exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = refund ? flags | 8 : flags &~ 8; - flags = pending ? flags | 16 : flags &~ 16; - flags = failed ? flags | 64 : flags &~ 64; - flags = gift ? flags | 1024 : flags &~ 1024; - flags = reaction ? flags | 2048 : flags &~ 2048; - flags = subscription ? flags | 4096 : flags &~ 4096; - stream.writeInt32(flags); - stream.writeInt64(stars); - stream.writeInt32(date); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeString(title); - } - if ((flags & 2) != 0) { - stream.writeString(description); - } - if ((flags & 4) != 0) { - photo.serializeToStream(stream); - } - if ((flags & 32) != 0) { - stream.writeInt32(transaction_date); - stream.writeString(transaction_url); - } - if ((flags & 128) != 0) { - stream.writeByteArray(bot_payload); - } - if ((flags & 256) != 0) { - stream.writeInt32(msg_id); - } - if ((flags & 512) != 0) { - stream.writeInt32(0x1cb5c415); - int count = extended_media.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - extended_media.get(i).serializeToStream(stream); - } - } - if ((flags & 4096) != 0) { - stream.writeInt32(subscription_period); - } - if ((flags & 8192) != 0) { - stream.writeInt32(giveaway_post_id); - } - } - } - - public static class TL_starsTransaction_layer186 extends TL_starsTransaction { - public static final int constructor = 0x433aeb2b; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - refund = (flags & 8) != 0; - pending = (flags & 16) != 0; - failed = (flags & 64) != 0; - gift = (flags & 1024) != 0; - reaction = (flags & 2048) != 0; - subscription = (flags & 4096) != 0; - id = stream.readString(exception); - stars = stream.readInt64(exception); - date = stream.readInt32(exception); - peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - title = stream.readString(exception); - } - if ((flags & 2) != 0) { - description = stream.readString(exception); - } - if ((flags & 4) != 0) { - photo = WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 32) != 0) { - transaction_date = stream.readInt32(exception); - transaction_url = stream.readString(exception); - } - if ((flags & 128) != 0) { - bot_payload = stream.readByteArray(exception); - } - if ((flags & 256) != 0) { - msg_id = stream.readInt32(exception); - } - if ((flags & 512) != 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++) { - MessageMedia object = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - extended_media.add(object); - } - } - if ((flags & 4096) != 0) { - subscription_period = stream.readInt32(exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = refund ? flags | 8 : flags &~ 8; - flags = pending ? flags | 16 : flags &~ 16; - flags = failed ? flags | 64 : flags &~ 64; - flags = gift ? flags | 1024 : flags &~ 1024; - flags = reaction ? flags | 2048 : flags &~ 2048; - flags = subscription ? flags | 4096 : flags &~ 4096; - stream.writeInt32(flags); - stream.writeInt64(stars); - stream.writeInt32(date); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeString(title); - } - if ((flags & 2) != 0) { - stream.writeString(description); - } - if ((flags & 4) != 0) { - photo.serializeToStream(stream); - } - if ((flags & 32) != 0) { - stream.writeInt32(transaction_date); - stream.writeString(transaction_url); - } - if ((flags & 128) != 0) { - stream.writeByteArray(bot_payload); - } - if ((flags & 256) != 0) { - stream.writeInt32(msg_id); - } - if ((flags & 512) != 0) { - stream.writeInt32(0x1cb5c415); - int count = extended_media.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - extended_media.get(i).serializeToStream(stream); - } - } - if ((flags & 4096) != 0) { - stream.writeInt32(subscription_period); - } - } - } - - public static class TL_starsTransaction_layer185 extends TL_starsTransaction { - public static final int constructor = 0x2db5418f; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - refund = (flags & 8) != 0; - pending = (flags & 16) != 0; - failed = (flags & 64) != 0; - gift = (flags & 1024) != 0; - id = stream.readString(exception); - stars = stream.readInt64(exception); - date = stream.readInt32(exception); - peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - title = stream.readString(exception); - } - if ((flags & 2) != 0) { - description = stream.readString(exception); - } - if ((flags & 4) != 0) { - photo = WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 32) != 0) { - transaction_date = stream.readInt32(exception); - transaction_url = stream.readString(exception); - } - if ((flags & 128) != 0) { - bot_payload = stream.readByteArray(exception); - } - if ((flags & 256) != 0) { - msg_id = stream.readInt32(exception); - } - if ((flags & 512) != 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++) { - MessageMedia object = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - extended_media.add(object); - } - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = refund ? flags | 8 : flags &~ 8; - flags = pending ? flags | 16 : flags &~ 16; - flags = failed ? flags | 64 : flags &~ 64; - flags = gift ? flags | 1024 : flags &~ 1024; - stream.writeInt32(flags); - stream.writeInt64(stars); - stream.writeInt32(date); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeString(title); - } - if ((flags & 2) != 0) { - stream.writeString(description); - } - if ((flags & 4) != 0) { - photo.serializeToStream(stream); - } - if ((flags & 32) != 0) { - stream.writeInt32(transaction_date); - stream.writeString(transaction_url); - } - if ((flags & 128) != 0) { - stream.writeByteArray(bot_payload); - } - if ((flags & 256) != 0) { - stream.writeInt32(msg_id); - } - if ((flags & 512) != 0) { - stream.writeInt32(0x1cb5c415); - int count = extended_media.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - extended_media.get(i).serializeToStream(stream); - } - } - } - } - - public static class TL_payments_starsStatus extends TLObject { - public static final int constructor = 0xbbfa316c; - - public int flags; - public long balance; - public ArrayList subscriptions = new ArrayList<>(); - public String subscriptions_next_offset; - public long subscriptions_missing_balance; - public ArrayList history = new ArrayList<>(); - public String next_offset; - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public static TL_payments_starsStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_payments_starsStatus.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_payments_starsStatus", constructor)); - } else { - return null; - } - } - TL_payments_starsStatus result = new TL_payments_starsStatus(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - balance = stream.readInt64(exception); - if ((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++) { - StarsSubscription object = StarsSubscription.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - subscriptions.add(object); - } - } - if ((flags & 4) != 0) { - subscriptions_next_offset = stream.readString(exception); - } - if ((flags & 16) != 0) { - subscriptions_missing_balance = stream.readInt64(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++) { - StarsTransaction object = StarsTransaction.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - history.add(object); - } - } - if ((flags & 1) != 0) { - next_offset = 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++) { - 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(flags); - stream.writeInt64(balance); - if ((flags & 2) != 0) { - stream.writeInt32(0x1cb5c415); - int count = subscriptions.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - subscriptions.get(i).serializeToStream(stream); - } - } - if ((flags & 4) != 0) { - stream.writeString(subscriptions_next_offset); - } - if ((flags & 16) != 0) { - stream.writeInt64(subscriptions_missing_balance); - } - stream.writeInt32(0x1cb5c415); - int count = history.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - history.get(i).serializeToStream(stream); - } - if ((flags & 1) != 0) { - stream.writeString(next_offset); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - chats.get(i).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int i = 0; i < count; ++i) { - users.get(i).serializeToStream(stream); - } - } - } - - public static class TL_payments_getStarsTopupOptions extends TLObject { - public static final int constructor = 0xc00ec7d3; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - Vector vector = new Vector(); - int size = stream.readInt32(exception); - for (int a = 0; a < size; a++) { - TL_starsTopupOption object = TL_starsTopupOption.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return vector; - } - vector.objects.add(object); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_payments_getStarsGiftOptions extends TLObject { - public static final int constructor = 0xd3c96bc8; - - public int flags; - public InputUser user_id; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - Vector vector = new Vector(); - int size = stream.readInt32(exception); - for (int a = 0; a < size; a++) { - TL_starsGiftOption object = TL_starsGiftOption.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return vector; - } - vector.objects.add(object); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - user_id.serializeToStream(stream); - } - } - } - - public static class TL_payments_getStarsGiveawayOptions extends TLObject { - public static final int constructor = 0xbd1efd3e; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - Vector vector = new Vector(); - int size = stream.readInt32(exception); - for (int a = 0; a < size; a++) { - TL_starsGiveawayOption object = TL_starsGiveawayOption.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return vector; - } - vector.objects.add(object); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_payments_getStarsStatus extends TLObject { - public static final int constructor = 0x104fcfa7; - - public InputPeer peer; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } - - public static class TL_payments_getStarsTransactions extends TLObject { - public static final int constructor = 0x673ac2f9; - - public int flags; - public boolean inbound; - public boolean outbound; - public InputPeer peer; - public String offset; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = inbound ? flags | 1 : flags &~ 1; - flags = outbound ? flags | 2 : flags &~ 2; - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeString(offset); - } - } - - public static class TL_payments_sendStarsForm extends TLObject { - public static final int constructor = 0x2bb731d; - - public int flags; - public long form_id; - public InputInvoice invoice; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_payments_paymentResult.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt64(form_id); - invoice.serializeToStream(stream); - } - } - public static class TL_factCheck extends TLObject { public static final int constructor = 0xb89bfccf; @@ -84137,196 +83769,4 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class StarsSubscription extends TLObject { - - public int flags; - public boolean canceled; - public boolean can_refulfill; - public boolean missing_balance; - public String id; - public Peer peer; - public int until_date; - public TL_starsSubscriptionPricing pricing; - public String chat_invite_hash; - - public static StarsSubscription TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - StarsSubscription result = null; - switch (constructor) { - case TL_starsSubscription.constructor: - result = new TL_starsSubscription(); - break; - case TL_starsSubscription_old.constructor: - result = new TL_starsSubscription_old(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in StarsTransaction", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - - } - - public static class TL_starsSubscription extends StarsSubscription { - public static final int constructor = 0x538ecf18; - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - canceled = (flags & 1) != 0; - can_refulfill = (flags & 2) != 0; - missing_balance = (flags & 4) != 0; - id = stream.readString(exception); - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - until_date = stream.readInt32(exception); - pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 8) != 0) { - chat_invite_hash = stream.readString(exception); - } - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = canceled ? (flags | 1) : (flags &~ 1); - flags = can_refulfill ? (flags | 2) : (flags &~ 2); - flags = missing_balance ? (flags | 4) : (flags &~ 4); - stream.writeInt32(flags); - stream.writeString(id); - peer.serializeToStream(stream); - stream.writeInt32(until_date); - pricing.serializeToStream(stream); - if ((flags & 8) != 0) { - stream.writeString(chat_invite_hash); - } - } - } - - public static class TL_starsSubscription_old extends TL_starsSubscription { - public static final int constructor = 0xd073f1e6; - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - canceled = (flags & 1) != 0; - can_refulfill = (flags & 2) != 0; - missing_balance = (flags & 4) != 0; - id = stream.readString(exception); - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - until_date = stream.readInt32(exception); - pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = canceled ? (flags | 1) : (flags &~ 1); - flags = can_refulfill ? (flags | 2) : (flags &~ 2); - flags = missing_balance ? (flags | 4) : (flags &~ 4); - stream.writeInt32(flags); - stream.writeString(id); - peer.serializeToStream(stream); - stream.writeInt32(until_date); - pricing.serializeToStream(stream); - } - } - - public static class TL_starsSubscriptionPricing extends TLObject { - public static final int constructor = 0x5416d58; - - public int period; - public long amount; - - public static TL_starsSubscriptionPricing TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_starsSubscriptionPricing.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_starsSubscriptionPricing", constructor)); - } else { - return null; - } - } - TL_starsSubscriptionPricing result = new TL_starsSubscriptionPricing(); - result.readParams(stream, exception); - return result; - } - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - period = stream.readInt32(exception); - amount = stream.readInt64(exception); - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(period); - stream.writeInt64(amount); - } - } - - public static class TL_getStarsSubscriptions extends TLObject { - public static final int constructor = 0x32512c5; - - public int flags; - public boolean missing_balance; - public InputPeer peer; - public String offset; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = missing_balance ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeString(offset); - } - } - - public static class TL_changeStarsSubscription extends TLObject { - public static final int constructor = 0xc7770878; - - public int flags; - public InputPeer peer; - public String subscription_id; - public Boolean canceled; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = (canceled != null) ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeString(subscription_id); - if ((flags & 1) != 0) { - stream.writeBool(canceled); - } - } - } - - public static class TL_fulfillStarsSubscription extends TLObject { - public static final int constructor = 0xcc5bebb3; - - public InputPeer peer; - public String subscription_id; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeString(subscription_id); - } - } - } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stars.java b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stars.java new file mode 100644 index 0000000000..fc32a640f2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stars.java @@ -0,0 +1,1785 @@ +package org.telegram.tgnet.tl; + +import org.telegram.tgnet.AbstractSerializedData; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; + +import java.util.ArrayList; + +public class TL_stars { + + public static class StarGift extends TLObject { + + public int flags; + public boolean limited; + public boolean sold_out; + public long id; + public TLRPC.Document sticker; + public long stars; + public int availability_remains; + public int availability_total; + public long convert_stars; + public int first_sale_date; + public int last_sale_date; + + public static StarGift TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StarGift result = null; + switch (constructor) { + case TL_starGift.constructor: + result = new TL_starGift(); + break; + case TL_starGift_layer190.constructor: + result = new TL_starGift_layer190(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StarGift", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + + } + + public static class TL_starGift extends StarGift { + public static final int constructor = 0x49c577cd; + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = limited ? flags | 1 : flags &~ 1; + flags = sold_out ? flags | 2 : flags &~ 2; + stream.writeInt32(flags); + stream.writeInt64(id); + sticker.serializeToStream(stream); + stream.writeInt64(stars); + if ((flags & 1) != 0) { + stream.writeInt32(availability_remains); + stream.writeInt32(availability_total); + } + stream.writeInt64(convert_stars); + if ((flags & 2) != 0) { + stream.writeInt32(first_sale_date); + stream.writeInt32(last_sale_date); + } + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + limited = (flags & 1) != 0; + sold_out = (flags & 2) != 0; + id = stream.readInt64(exception); + sticker = TLRPC.Document.TLdeserialize(stream, stream.readInt32(exception), exception); + stars = stream.readInt64(exception); + if ((flags & 1) != 0) { + availability_remains = stream.readInt32(exception); + availability_total = stream.readInt32(exception); + } + convert_stars = stream.readInt64(exception); + if ((flags & 2) != 0) { + first_sale_date = stream.readInt32(exception); + last_sale_date = stream.readInt32(exception); + } + } + } + + public static class TL_starGift_layer190 extends TL_starGift { + public static final int constructor = 0xaea174ee; + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = limited ? flags | 1 : flags &~ 1; + stream.writeInt32(flags); + stream.writeInt64(id); + sticker.serializeToStream(stream); + stream.writeInt64(stars); + if ((flags & 1) != 0) { + stream.writeInt32(availability_remains); + stream.writeInt32(availability_total); + } + stream.writeInt64(convert_stars); + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + limited = (flags & 1) != 0; + id = stream.readInt64(exception); + sticker = TLRPC.Document.TLdeserialize(stream, stream.readInt32(exception), exception); + stars = stream.readInt64(exception); + if ((flags & 1) != 0) { + availability_remains = stream.readInt32(exception); + availability_total = stream.readInt32(exception); + } + convert_stars = stream.readInt64(exception); + sold_out = limited && availability_remains <= 0; + } + } + + public static class StarGifts extends TLObject { + public static StarGifts TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StarGifts result = null; + switch (constructor) { + case TL_starGifts.constructor: + result = new TL_starGifts(); + break; + case TL_starGiftsNotModified.constructor: + result = new TL_starGiftsNotModified(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StarGifts", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_starGifts extends StarGifts { + public static final int constructor = 0x901689ea; + + public int hash; + public ArrayList gifts = new ArrayList<>(); + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(hash); + stream.writeInt32(0x1cb5c415); + int count = gifts.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + gifts.get(a).serializeToStream(stream); + } + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + hash = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + StarGift gift = StarGift.TLdeserialize(stream, stream.readInt32(exception), exception); + if (gift == null) { + return; + } + gifts.add(gift); + } + } + } + public static class TL_starGiftsNotModified extends StarGifts { + public static final int constructor = 0xa388a368; + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) {} + } + + public static class getStarGifts extends TLObject { + public static final int constructor = 0xc4563590; + + public int hash; + + @Override + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return StarGifts.TLdeserialize(stream, constructor, exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(hash); + } + } + + public static class getUserStarGifts extends TLObject { + public static final int constructor = 0x5e72c7e1; + + public TLRPC.InputUser user_id; + public String offset; + public int limit; + + @Override + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_userStarGifts.TLdeserialize(stream, constructor, exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + user_id.serializeToStream(stream); + stream.writeString(offset); + stream.writeInt32(limit); + } + } + + public static class TL_userStarGifts extends TLObject { + public static final int constructor = 0x6b65b517; + + public int flags; + public int count; + public ArrayList gifts = new ArrayList<>(); + public String next_offset; + public ArrayList users = new ArrayList<>(); + + public static TL_userStarGifts TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + TL_userStarGifts result = null; + switch (constructor) { + case TL_userStarGifts.constructor: + result = new TL_userStarGifts(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_userStarGifts", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + count = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + UserStarGift gift = UserStarGift.TLdeserialize(stream, stream.readInt32(exception), exception); + if (gift == null) { + return; + } + gifts.add(gift); + } + if ((flags & 1) != 0) { + next_offset = stream.readString(exception); + } + 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++) { + TLRPC.User user = TLRPC.User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (user == null) { + return; + } + users.add(user); + } + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(count); + stream.writeInt32(0x1cb5c415); + stream.writeInt32(gifts.size()); + for (int a = 0; a < gifts.size(); a++) { + gifts.get(a).serializeToStream(stream); + } + if ((flags & 1) != 0) { + stream.writeString(next_offset); + } + stream.writeInt32(0x1cb5c415); + stream.writeInt32(users.size()); + for (int a = 0; a < users.size(); a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class UserStarGift extends TLObject { + + public int flags; + public boolean name_hidden; + public boolean unsaved; + public long from_id; + public int date; + public TL_stars.StarGift gift; + public TLRPC.TL_textWithEntities message; + public int msg_id; + public long convert_stars; + + public static UserStarGift TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + UserStarGift result = null; + switch (constructor) { + case TL_userStarGift.constructor: + result = new TL_userStarGift(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in UserStarGift", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static class TL_userStarGift extends UserStarGift { + public static final int constructor = 0xeea49a6e; + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = name_hidden ? flags | 1 : flags &~ 1; + flags = unsaved ? flags | 32 : flags &~ 32; + stream.writeInt32(flags); + if ((flags & 2) != 0) { + stream.writeInt64(from_id); + } + stream.writeInt32(date); + gift.serializeToStream(stream); + if ((flags & 4) != 0) { + message.serializeToStream(stream); + } + if ((flags & 8) != 0) { + stream.writeInt32(msg_id); + } + if ((flags & 16) != 0) { + stream.writeInt64(convert_stars); + } + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + name_hidden = (flags & 1) != 0; + unsaved = (flags & 32) != 0; + if ((flags & 2) != 0) { + from_id = stream.readInt64(exception); + } + date = stream.readInt32(exception); + gift = TL_stars.StarGift.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + message = TLRPC.TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 8) != 0) { + msg_id = stream.readInt32(exception); + } + if ((flags & 16) != 0) { + convert_stars = stream.readInt64(exception); + } + } + } + + public static class saveStarGift extends TLObject { + public static final int constructor = 0x87acf08e; + + public int flags; + public boolean unsave; + public TLRPC.InputUser user_id; + public int msg_id; + + @Override + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = unsave ? flags | 1 : flags &~ 1; + stream.writeInt32(flags); + user_id.serializeToStream(stream); + stream.writeInt32(msg_id); + } + } + + public static class convertStarGift extends TLObject { + public static final int constructor = 0x421e027; + + public TLRPC.InputUser user_id; + public int msg_id; + + @Override + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + user_id.serializeToStream(stream); + stream.writeInt32(msg_id); + } + } + + public static class TL_starsTopupOption extends TLObject { + public static final int constructor = 0xbd915c0; + + public int flags; + public boolean extended; + public long stars; + public String store_product; + public String currency; + public long amount; + public boolean loadingStorePrice; //custom + public boolean missingStorePrice; //custom + + public static TL_starsTopupOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_starsTopupOption.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_starsTopupOption", constructor)); + } else { + return null; + } + } + TL_starsTopupOption result = new TL_starsTopupOption(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + extended = (flags & 2) != 0; + stars = stream.readInt64(exception); + if ((flags & 1) != 0) { + store_product = stream.readString(exception); + } + currency = stream.readString(exception); + amount = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = extended ? flags | 2 : flags &~ 2; + stream.writeInt32(flags); + stream.writeInt64(stars); + if ((flags & 1) != 0) { + stream.writeString(store_product); + } + stream.writeString(currency); + stream.writeInt64(amount); + } + } + + public static class TL_starsGiftOption extends TLObject { + public static final int constructor = 0x5e0589f1; + + public int flags; + public boolean extended; + public long stars; + public String store_product; + public String currency; + public long amount; + public boolean loadingStorePrice; //custom + public boolean missingStorePrice; //custom + + public static TL_starsGiftOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_starsGiftOption.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_starsGiftOption", constructor)); + } else { + return null; + } + } + TL_starsGiftOption result = new TL_starsGiftOption(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + extended = (flags & 2) != 0; + stars = stream.readInt64(exception); + if ((flags & 1) != 0) { + store_product = stream.readString(exception); + } + currency = stream.readString(exception); + amount = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = extended ? flags | 2 : flags &~ 2; + stream.writeInt32(flags); + stream.writeInt64(stars); + if ((flags & 1) != 0) { + stream.writeString(store_product); + } + stream.writeString(currency); + stream.writeInt64(amount); + } + } + + public static class TL_starsGiveawayWinnersOption extends TLObject { + public static final int constructor = 0x54236209; + + public int flags; + public boolean isDefault; + public int users; + public long per_user_stars; + + public static TL_starsGiveawayWinnersOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_starsGiveawayWinnersOption.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_starsGiveawayWinnersOption", constructor)); + } else { + return null; + } + } + TL_starsGiveawayWinnersOption result = new TL_starsGiveawayWinnersOption(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + isDefault = (flags & 1) != 0; + users = stream.readInt32(exception); + per_user_stars = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = isDefault ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(users); + stream.writeInt64(per_user_stars); + } + } + + public static class TL_starsGiveawayOption extends TLObject { + public static final int constructor = 0x94ce852a; + + public int flags; + public boolean extended; + public boolean isDefault; + public long stars; + public int yearly_boosts; + public String store_product; + public String currency; + public long amount; + public ArrayList winners = new ArrayList<>(); + + public boolean loadingStorePrice; //custom + public boolean missingStorePrice; //custom + + public static TL_starsGiveawayOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_starsGiveawayOption.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_starsGiveawayOption", constructor)); + } else { + return null; + } + } + TL_starsGiveawayOption result = new TL_starsGiveawayOption(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + extended = (flags & 1) != 0; + isDefault = (flags & 2) != 0; + stars = stream.readInt64(exception); + yearly_boosts = stream.readInt32(exception); + if ((flags & 4) != 0) { + store_product = stream.readString(exception); + } + currency = stream.readString(exception); + amount = 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++) { + TL_starsGiveawayWinnersOption object = TL_starsGiveawayWinnersOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + winners.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = extended ? (flags | 1) : (flags &~ 1); + flags = isDefault ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(yearly_boosts); + if ((flags & 4) != 0) { + stream.writeString(store_product); + } + stream.writeString(currency); + stream.writeInt64(amount); + stream.writeInt32(0x1cb5c415); + int count = winners.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + winners.get(i).serializeToStream(stream); + } + } + } + + public static class StarsTransactionPeer extends TLObject { + + public TLRPC.Peer peer; + + public static StarsTransactionPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StarsTransactionPeer result = null; + switch (constructor) { + case TL_starsTransactionPeer.constructor: + result = new TL_starsTransactionPeer(); + break; + case TL_starsTransactionPeerAppStore.constructor: + result = new TL_starsTransactionPeerAppStore(); + break; + case TL_starsTransactionPeerPlayMarket.constructor: + result = new TL_starsTransactionPeerPlayMarket(); + break; + case TL_starsTransactionPeerFragment.constructor: + result = new TL_starsTransactionPeerFragment(); + break; + case TL_starsTransactionPeerPremiumBot.constructor: + result = new TL_starsTransactionPeerPremiumBot(); + break; + case TL_starsTransactionPeerUnsupported.constructor: + result = new TL_starsTransactionPeerUnsupported(); + break; + case TL_starsTransactionPeerAds.constructor: + result = new TL_starsTransactionPeerAds(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StarsTransactionPeer", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_starsTransactionPeer extends StarsTransactionPeer { + public static final int constructor = 0xd80da15d; + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } + + public static class TL_starsTransactionPeerAppStore extends StarsTransactionPeer { + public static final int constructor = 0xb457b375; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_starsTransactionPeerPlayMarket extends StarsTransactionPeer { + public static final int constructor = 0x7b560a0b; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_starsTransactionPeerFragment extends StarsTransactionPeer { + public static final int constructor = 0xe92fd902; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_starsTransactionPeerPremiumBot extends StarsTransactionPeer { + public static final int constructor = 0x250dbaf8; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_starsTransactionPeerUnsupported extends StarsTransactionPeer { + public static final int constructor = 0x95f2bfe4; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_starsTransactionPeerAds extends StarsTransactionPeer { + public static final int constructor = 0x60682812; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class StarsTransaction extends TLObject { + + public int flags; + public boolean refund; + public boolean pending; + public boolean failed; + public boolean gift; + public boolean reaction; + public boolean subscription; + public String id; + public long stars; + public int date; + public StarsTransactionPeer peer; + public String title; + public String description; + public TLRPC.WebDocument photo; + public int transaction_date; + public String transaction_url; + public byte[] bot_payload; + public int msg_id; + public ArrayList extended_media = new ArrayList<>(); + public int subscription_period; + public int giveaway_post_id; + public StarGift stargift; + + public TLRPC.Peer sent_by; //custom + public TLRPC.Peer received_by; //custom + + public static StarsTransaction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StarsTransaction result = null; + switch (constructor) { + case TL_starsTransaction_layer181.constructor: + result = new TL_starsTransaction_layer181(); + break; + case TL_starsTransaction_layer182.constructor: + result = new TL_starsTransaction_layer182(); + break; + case TL_starsTransaction_layer185.constructor: + result = new TL_starsTransaction_layer185(); + break; + case TL_starsTransaction_layer186.constructor: + result = new TL_starsTransaction_layer186(); + break; + case TL_starsTransaction_layer188.constructor: + result = new TL_starsTransaction_layer188(); + break; + case TL_starsTransaction.constructor: + result = new TL_starsTransaction(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StarsTransaction", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + + } + + public static class TL_starsTransaction_layer181 extends StarsTransaction { + public static final int constructor = 0xcc7079b2; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + refund = (flags & 8) != 0; + id = stream.readString(exception); + stars = stream.readInt64(exception); + date = stream.readInt32(exception); + peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + title = stream.readString(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 4) != 0) { + photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = refund ? flags | 8 : flags &~ 8; + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(date); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(title); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 4) != 0) { + photo.serializeToStream(stream); + } + } + } + + public static class TL_starsTransaction_layer182 extends TL_starsTransaction { + public static final int constructor = 0xaa00c898; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + refund = (flags & 8) != 0; + pending = (flags & 16) != 0; + failed = (flags & 64) != 0; + id = stream.readString(exception); + stars = stream.readInt64(exception); + date = stream.readInt32(exception); + peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + title = stream.readString(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 4) != 0) { + photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + transaction_date = stream.readInt32(exception); + transaction_url = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = refund ? flags | 8 : flags &~ 8; + flags = pending ? flags | 16 : flags &~ 16; + flags = failed ? flags | 64 : flags &~ 64; + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(date); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(title); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 4) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeInt32(transaction_date); + stream.writeString(transaction_url); + } + } + } + + public static class TL_starsTransaction extends StarsTransaction { + public static final int constructor = 0xa9ee4c2; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + refund = (flags & 8) != 0; + pending = (flags & 16) != 0; + failed = (flags & 64) != 0; + gift = (flags & 1024) != 0; + reaction = (flags & 2048) != 0; + subscription = (flags & 4096) != 0; + id = stream.readString(exception); + stars = stream.readInt64(exception); + date = stream.readInt32(exception); + peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + title = stream.readString(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 4) != 0) { + photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + transaction_date = stream.readInt32(exception); + transaction_url = stream.readString(exception); + } + if ((flags & 128) != 0) { + bot_payload = stream.readByteArray(exception); + } + if ((flags & 256) != 0) { + msg_id = stream.readInt32(exception); + } + if ((flags & 512) != 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++) { + TLRPC.MessageMedia object = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + extended_media.add(object); + } + } + if ((flags & 4096) != 0) { + subscription_period = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + giveaway_post_id = stream.readInt32(exception); + } + if ((flags & 16384) != 0) { + stargift = StarGift.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = refund ? flags | 8 : flags &~ 8; + flags = pending ? flags | 16 : flags &~ 16; + flags = failed ? flags | 64 : flags &~ 64; + flags = gift ? flags | 1024 : flags &~ 1024; + flags = reaction ? flags | 2048 : flags &~ 2048; + flags = subscription ? flags | 4096 : flags &~ 4096; + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(date); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(title); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 4) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeInt32(transaction_date); + stream.writeString(transaction_url); + } + if ((flags & 128) != 0) { + stream.writeByteArray(bot_payload); + } + if ((flags & 256) != 0) { + stream.writeInt32(msg_id); + } + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = extended_media.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + extended_media.get(i).serializeToStream(stream); + } + } + if ((flags & 4096) != 0) { + stream.writeInt32(subscription_period); + } + if ((flags & 8192) != 0) { + stream.writeInt32(giveaway_post_id); + } + if ((flags & 16384) != 0) { + stargift.serializeToStream(stream); + } + } + } + + public static class TL_starsTransaction_layer188 extends TL_starsTransaction { + public static final int constructor = 0xee7522d5; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + refund = (flags & 8) != 0; + pending = (flags & 16) != 0; + failed = (flags & 64) != 0; + gift = (flags & 1024) != 0; + reaction = (flags & 2048) != 0; + subscription = (flags & 4096) != 0; + id = stream.readString(exception); + stars = stream.readInt64(exception); + date = stream.readInt32(exception); + peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + title = stream.readString(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 4) != 0) { + photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + transaction_date = stream.readInt32(exception); + transaction_url = stream.readString(exception); + } + if ((flags & 128) != 0) { + bot_payload = stream.readByteArray(exception); + } + if ((flags & 256) != 0) { + msg_id = stream.readInt32(exception); + } + if ((flags & 512) != 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++) { + TLRPC.MessageMedia object = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + extended_media.add(object); + } + } + if ((flags & 4096) != 0) { + subscription_period = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + giveaway_post_id = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = refund ? flags | 8 : flags &~ 8; + flags = pending ? flags | 16 : flags &~ 16; + flags = failed ? flags | 64 : flags &~ 64; + flags = gift ? flags | 1024 : flags &~ 1024; + flags = reaction ? flags | 2048 : flags &~ 2048; + flags = subscription ? flags | 4096 : flags &~ 4096; + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(date); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(title); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 4) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeInt32(transaction_date); + stream.writeString(transaction_url); + } + if ((flags & 128) != 0) { + stream.writeByteArray(bot_payload); + } + if ((flags & 256) != 0) { + stream.writeInt32(msg_id); + } + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = extended_media.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + extended_media.get(i).serializeToStream(stream); + } + } + if ((flags & 4096) != 0) { + stream.writeInt32(subscription_period); + } + if ((flags & 8192) != 0) { + stream.writeInt32(giveaway_post_id); + } + } + } + + public static class TL_starsTransaction_layer186 extends TL_starsTransaction { + public static final int constructor = 0x433aeb2b; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + refund = (flags & 8) != 0; + pending = (flags & 16) != 0; + failed = (flags & 64) != 0; + gift = (flags & 1024) != 0; + reaction = (flags & 2048) != 0; + subscription = (flags & 4096) != 0; + id = stream.readString(exception); + stars = stream.readInt64(exception); + date = stream.readInt32(exception); + peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + title = stream.readString(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 4) != 0) { + photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + transaction_date = stream.readInt32(exception); + transaction_url = stream.readString(exception); + } + if ((flags & 128) != 0) { + bot_payload = stream.readByteArray(exception); + } + if ((flags & 256) != 0) { + msg_id = stream.readInt32(exception); + } + if ((flags & 512) != 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++) { + TLRPC.MessageMedia object = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + extended_media.add(object); + } + } + if ((flags & 4096) != 0) { + subscription_period = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = refund ? flags | 8 : flags &~ 8; + flags = pending ? flags | 16 : flags &~ 16; + flags = failed ? flags | 64 : flags &~ 64; + flags = gift ? flags | 1024 : flags &~ 1024; + flags = reaction ? flags | 2048 : flags &~ 2048; + flags = subscription ? flags | 4096 : flags &~ 4096; + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(date); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(title); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 4) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeInt32(transaction_date); + stream.writeString(transaction_url); + } + if ((flags & 128) != 0) { + stream.writeByteArray(bot_payload); + } + if ((flags & 256) != 0) { + stream.writeInt32(msg_id); + } + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = extended_media.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + extended_media.get(i).serializeToStream(stream); + } + } + if ((flags & 4096) != 0) { + stream.writeInt32(subscription_period); + } + } + } + + public static class TL_starsTransaction_layer185 extends TL_starsTransaction { + public static final int constructor = 0x2db5418f; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + refund = (flags & 8) != 0; + pending = (flags & 16) != 0; + failed = (flags & 64) != 0; + gift = (flags & 1024) != 0; + id = stream.readString(exception); + stars = stream.readInt64(exception); + date = stream.readInt32(exception); + peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + title = stream.readString(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 4) != 0) { + photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + transaction_date = stream.readInt32(exception); + transaction_url = stream.readString(exception); + } + if ((flags & 128) != 0) { + bot_payload = stream.readByteArray(exception); + } + if ((flags & 256) != 0) { + msg_id = stream.readInt32(exception); + } + if ((flags & 512) != 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++) { + TLRPC.MessageMedia object = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + extended_media.add(object); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = refund ? flags | 8 : flags &~ 8; + flags = pending ? flags | 16 : flags &~ 16; + flags = failed ? flags | 64 : flags &~ 64; + flags = gift ? flags | 1024 : flags &~ 1024; + stream.writeInt32(flags); + stream.writeInt64(stars); + stream.writeInt32(date); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(title); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 4) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeInt32(transaction_date); + stream.writeString(transaction_url); + } + if ((flags & 128) != 0) { + stream.writeByteArray(bot_payload); + } + if ((flags & 256) != 0) { + stream.writeInt32(msg_id); + } + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = extended_media.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + extended_media.get(i).serializeToStream(stream); + } + } + } + } + + public static class TL_payments_starsStatus extends TLObject { + public static final int constructor = 0xbbfa316c; + + public int flags; + public long balance; + public ArrayList subscriptions = new ArrayList<>(); + public String subscriptions_next_offset; + public long subscriptions_missing_balance; + public ArrayList history = new ArrayList<>(); + public String next_offset; + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_payments_starsStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_payments_starsStatus.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_payments_starsStatus", constructor)); + } else { + return null; + } + } + TL_payments_starsStatus result = new TL_payments_starsStatus(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + balance = stream.readInt64(exception); + if ((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++) { + StarsSubscription object = StarsSubscription.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + subscriptions.add(object); + } + } + if ((flags & 4) != 0) { + subscriptions_next_offset = stream.readString(exception); + } + if ((flags & 16) != 0) { + subscriptions_missing_balance = stream.readInt64(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++) { + StarsTransaction object = StarsTransaction.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + history.add(object); + } + } + if ((flags & 1) != 0) { + next_offset = 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++) { + TLRPC.Chat object = TLRPC.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++) { + TLRPC.User object = TLRPC.User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt64(balance); + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = subscriptions.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + subscriptions.get(i).serializeToStream(stream); + } + } + if ((flags & 4) != 0) { + stream.writeString(subscriptions_next_offset); + } + if ((flags & 16) != 0) { + stream.writeInt64(subscriptions_missing_balance); + } + stream.writeInt32(0x1cb5c415); + int count = history.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + history.get(i).serializeToStream(stream); + } + if ((flags & 1) != 0) { + stream.writeString(next_offset); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + chats.get(i).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int i = 0; i < count; ++i) { + users.get(i).serializeToStream(stream); + } + } + } + + public static class TL_payments_getStarsTopupOptions extends TLObject { + public static final int constructor = 0xc00ec7d3; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + TLRPC.Vector vector = new TLRPC.Vector(); + int size = stream.readInt32(exception); + for (int a = 0; a < size; a++) { + TL_starsTopupOption object = TL_starsTopupOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_payments_getStarsGiftOptions extends TLObject { + public static final int constructor = 0xd3c96bc8; + + public int flags; + public TLRPC.InputUser user_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + TLRPC.Vector vector = new TLRPC.Vector(); + int size = stream.readInt32(exception); + for (int a = 0; a < size; a++) { + TL_starsGiftOption object = TL_starsGiftOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + user_id.serializeToStream(stream); + } + } + } + + public static class TL_payments_getStarsGiveawayOptions extends TLObject { + public static final int constructor = 0xbd1efd3e; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + TLRPC.Vector vector = new TLRPC.Vector(); + int size = stream.readInt32(exception); + for (int a = 0; a < size; a++) { + TL_starsGiveawayOption object = TL_starsGiveawayOption.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_payments_getStarsStatus extends TLObject { + public static final int constructor = 0x104fcfa7; + + public TLRPC.InputPeer peer; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } + + public static class TL_payments_getStarsTransactions extends TLObject { + public static final int constructor = 0x673ac2f9; + + public int flags; + public boolean inbound; + public boolean outbound; + public TLRPC.InputPeer peer; + public String offset; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = inbound ? flags | 1 : flags &~ 1; + flags = outbound ? flags | 2 : flags &~ 2; + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeString(offset); + } + } + + public static class TL_payments_sendStarsForm extends TLObject { + public static final int constructor = 0x7998c914; + + public long form_id; + public TLRPC.InputInvoice invoice; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.TL_payments_paymentResult.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(form_id); + invoice.serializeToStream(stream); + } + } + + public static class StarsSubscription extends TLObject { + + public int flags; + public boolean canceled; + public boolean can_refulfill; + public boolean missing_balance; + public String id; + public TLRPC.Peer peer; + public int until_date; + public TL_starsSubscriptionPricing pricing; + public String chat_invite_hash; + + public static StarsSubscription TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StarsSubscription result = null; + switch (constructor) { + case TL_starsSubscription.constructor: + result = new TL_starsSubscription(); + break; + case TL_starsSubscription_old.constructor: + result = new TL_starsSubscription_old(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StarsTransaction", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + + } + + public static class TL_starsSubscription extends StarsSubscription { + public static final int constructor = 0x538ecf18; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + canceled = (flags & 1) != 0; + can_refulfill = (flags & 2) != 0; + missing_balance = (flags & 4) != 0; + id = stream.readString(exception); + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + until_date = stream.readInt32(exception); + pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8) != 0) { + chat_invite_hash = stream.readString(exception); + } + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = canceled ? (flags | 1) : (flags &~ 1); + flags = can_refulfill ? (flags | 2) : (flags &~ 2); + flags = missing_balance ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + stream.writeString(id); + peer.serializeToStream(stream); + stream.writeInt32(until_date); + pricing.serializeToStream(stream); + if ((flags & 8) != 0) { + stream.writeString(chat_invite_hash); + } + } + } + + public static class TL_starsSubscription_old extends TL_starsSubscription { + public static final int constructor = 0xd073f1e6; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + canceled = (flags & 1) != 0; + can_refulfill = (flags & 2) != 0; + missing_balance = (flags & 4) != 0; + id = stream.readString(exception); + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + until_date = stream.readInt32(exception); + pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = canceled ? (flags | 1) : (flags &~ 1); + flags = can_refulfill ? (flags | 2) : (flags &~ 2); + flags = missing_balance ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + stream.writeString(id); + peer.serializeToStream(stream); + stream.writeInt32(until_date); + pricing.serializeToStream(stream); + } + } + + public static class TL_starsSubscriptionPricing extends TLObject { + public static final int constructor = 0x5416d58; + + public int period; + public long amount; + + public static TL_starsSubscriptionPricing TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_starsSubscriptionPricing.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_starsSubscriptionPricing", constructor)); + } else { + return null; + } + } + TL_starsSubscriptionPricing result = new TL_starsSubscriptionPricing(); + result.readParams(stream, exception); + return result; + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + period = stream.readInt32(exception); + amount = stream.readInt64(exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(period); + stream.writeInt64(amount); + } + } + + public static class TL_getStarsSubscriptions extends TLObject { + public static final int constructor = 0x32512c5; + + public int flags; + public boolean missing_balance; + public TLRPC.InputPeer peer; + public String offset; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = missing_balance ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeString(offset); + } + } + + public static class TL_changeStarsSubscription extends TLObject { + public static final int constructor = 0xc7770878; + + public int flags; + public TLRPC.InputPeer peer; + public String subscription_id; + public Boolean canceled; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = (canceled != null) ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeString(subscription_id); + if ((flags & 1) != 0) { + stream.writeBool(canceled); + } + } + } + + public static class TL_fulfillStarsSubscription extends TLObject { + public static final int constructor = 0xcc5bebb3; + + public TLRPC.InputPeer peer; + public String subscription_id; + + 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.writeString(subscription_id); + } + } +} 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 d5a11d54bd..ec80c05516 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 @@ -1468,15 +1468,15 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_stories_report extends TLObject { - public static final int constructor = 0x1923fa8c; + public static final int constructor = 0x19d8eb45; public TLRPC.InputPeer peer; public ArrayList id = new ArrayList<>(); - public TLRPC.ReportReason reason; + public byte[] option; public String message; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + return TLRPC.ReportResult.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -1488,7 +1488,7 @@ public void serializeToStream(AbstractSerializedData stream) { for (int a = 0; a < count; a++) { stream.writeInt32(id.get(a)); } - reason.serializeToStream(stream); + stream.writeByteArray(option); stream.writeString(message); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index fb84a5f63f..04f87e69da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -644,20 +644,6 @@ protected void onDetachedFromWindow() { return actionMode; } - public void onDrawCrossfadeBackground(Canvas canvas) { - if (blurredBackground && actionBarColor != Color.TRANSPARENT) { - rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); - blurScrimPaint.setColor(actionBarColor); - contentView.drawBlurRect(canvas, getY(), rectTmp, blurScrimPaint, true); - } else { - Drawable drawable = getBackground(); - if (drawable != null) { - drawable.setBounds(0, 0, getWidth(), getHeight()); - drawable.draw(canvas); - } - } - } - public void onDrawCrossfadeContent(Canvas canvas, boolean front, boolean hideBackDrawable, float progress) { for (int i = 0; i < getChildCount(); i++) { View ch = getChildAt(i); 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 35ff306150..b06c0b0dee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -619,7 +619,7 @@ public View addSubItem(int id, View cell) { return cell; } - public ActionBarMenuSubItem addSwipeBackItem(int icon, Drawable iconDrawable, String text, View viewToSwipeBack) { + public ActionBarMenuSubItem addSwipeBackItem(int icon, Drawable iconDrawable, String text, View viewToSwipeBack) { createPopupLayout(); ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext(), false, false, false, resourcesProvider); @@ -2536,11 +2536,11 @@ private void layoutLazyItems() { lazyList.clear(); } - public static ActionBarMenuSubItem addItem(ActionBarPopupWindow.ActionBarPopupWindowLayout windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) { + public static ActionBarMenuSubItem addItem(ViewGroup windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) { return addItem(false, false, windowLayout, icon, text, needCheck, resourcesProvider); } - public static ActionBarMenuSubItem addItem(boolean first, boolean last, ActionBarPopupWindow.ActionBarPopupWindowLayout windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) { + public static ActionBarMenuSubItem addItem(boolean first, boolean last, ViewGroup windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(windowLayout.getContext(), needCheck, first, last, resourcesProvider); cell.setTextAndIcon(text, icon); cell.setMinimumWidth(AndroidUtilities.dp(196)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java index dd9a24747b..fb6bab0a5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -156,7 +156,12 @@ public void setRightIcon(int icon) { } textView.setLayoutParams(layoutParams); setPadding(dp(LocaleController.isRTL ? 8 : 18), 0, dp(LocaleController.isRTL ? 18 : 8), 0); - rightIcon.setImageResource(icon); + if (icon == 0) { + rightIcon.setVisibility(View.GONE); + } else { + rightIcon.setVisibility(View.VISIBLE); + rightIcon.setImageResource(icon); + } } public void setTextAndIcon(CharSequence text, int icon) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index 242aba83b3..663acc42e0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -43,6 +43,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PopupSwipeBackLayout; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java index 2dfebb92f7..0a44bde40d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -102,6 +102,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati private boolean[] shadowVisibility = new boolean[2]; private AnimatorSet[] shadowAnimation = new AnimatorSet[2]; private int customViewOffset = 12; + private boolean withCancelDialog; private int dialogButtonColorKey = Theme.key_dialogButton; @@ -290,6 +291,7 @@ public AlertDialog(Context context, int progressStyle, Theme.ResourcesProvider r shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY)); shadowDrawable.getPadding(backgroundPaddings); } + withCancelDialog = progressViewStyle == ALERT_TYPE_SPINNER; progressViewStyle = progressStyle; } @@ -313,6 +315,10 @@ public void show() { shownAt = System.currentTimeMillis(); } + public void setCancelDialog(boolean enable) { + withCancelDialog = enable; + } + public class AlertDialogView extends LinearLayout { public AlertDialogView(Context context) { super(context); @@ -322,7 +328,7 @@ public AlertDialogView(Context context) { @Override public boolean onTouchEvent(MotionEvent event) { - if (progressViewStyle == ALERT_TYPE_SPINNER) { + if (withCancelDialog) { showCancelAlert(); return false; } @@ -331,7 +337,7 @@ public boolean onTouchEvent(MotionEvent event) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (progressViewStyle == ALERT_TYPE_SPINNER) { + if (withCancelDialog) { showCancelAlert(); return false; } @@ -1218,7 +1224,7 @@ public void setMessageLineSpacing(float spaceDp) { } } - private void showCancelAlert() { + public void showCancelAlert() { if (!canCacnel || cancelDialog != null) { return; } 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 dcc5a4ea2c..ec0f05e782 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -1434,7 +1434,7 @@ public void show() { } backDrawable.setAlpha(0); layoutCount = 2; - containerView.setTranslationY((Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight * (1f - hideSystemVerticalInsetsProgress) : 0) + containerView.getMeasuredHeight() + (scrollNavBar ? getBottomInset() : 0)); + containerView.setTranslationY((Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight * (1f - hideSystemVerticalInsetsProgress) : 0) + containerView.getMeasuredHeight() + (scrollNavBar ? Math.max(0, Math.min(AndroidUtilities.navigationBarHeight, getBottomInset())) : 0)); long delay = openNoDelay ? 0 : 150; if (waitingKeyboard) { delay = 500; @@ -1565,7 +1565,7 @@ private void startOpenAnimation() { containerView.setAlpha(0); containerView.setTranslationY(0); } else { - containerView.setTranslationY(getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)); + containerView.setTranslationY(getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? Math.max(0, Math.min(AndroidUtilities.navigationBarHeight, getBottomInset())) : 0)); } currentSheetAnimationType = 1; if (navigationBarAnimation != null) { @@ -1709,7 +1709,7 @@ public void dismissWithButtonClick(final int item) { currentSheetAnimationType = 2; currentSheetAnimation = new AnimatorSet(); currentSheetAnimation.playTogether( - ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), + ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? Math.max(0, Math.min(AndroidUtilities.navigationBarHeight, getBottomInset())) : 0)), ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0) ); currentSheetAnimation.setDuration(cellType == Builder.CELL_TYPE_CALL ? 330 : 180); @@ -1849,7 +1849,7 @@ public void dismiss() { animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_X, AndroidUtilities.dp(48))); animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0)); } else { - animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + (forceKeyboardOnDismiss ? lastKeyboardHeight : keyboardHeight) + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0))); + animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + (forceKeyboardOnDismiss ? lastKeyboardHeight : keyboardHeight) + AndroidUtilities.dp(10) + (scrollNavBar ? Math.max(0, Math.min(AndroidUtilities.navigationBarHeight, getBottomInset())) : 0))); } } animators.add(ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0)); @@ -1942,7 +1942,7 @@ public int getNavigationBarColor(int color) { } else if (transitionFromRight) { t = containerView.getAlpha(); } else { - final float fullHeight = getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0); + final float fullHeight = getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? Math.max(0, Math.min(AndroidUtilities.navigationBarHeight, getBottomInset())) : 0); t = Utilities.clamp01(1f - containerView.getTranslationY() / fullHeight); } return ColorUtils.blendARGB(color, navBarColor, t); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabDialog.java index 03e1693031..f9da58e376 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabDialog.java @@ -19,6 +19,7 @@ import androidx.annotation.Nullable; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.LaunchActivity; @@ -139,14 +140,22 @@ public float drawInto(Canvas canvas, RectF finalRect, float progress, RectF clip public void attach() { if (attached) return; attached = true; - super.show(); + try { + super.show(); + } catch (Exception e) { + FileLog.e(e); + } } public void detach() { sheet.setDialog(null); if (!attached) return; attached = false; - super.dismiss(); + try { + super.dismiss(); + } catch (Exception e) { + FileLog.e(e); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabsOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabsOverlay.java index e42571ee14..370b8b4ef6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabsOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheetTabsOverlay.java @@ -382,11 +382,11 @@ public float getScrollRange(boolean animated) { } public float getScrollWindow() { - return Math.min(SharedConfig.botTabs3DEffect ? 3 : 6, getScrollRange()); + return Math.min(3, getScrollRange()); } public float getScrollWindow(boolean animated) { - return Math.min(SharedConfig.botTabs3DEffect ? 3 : 6, getScrollRange(animated)); + return Math.min(3, getScrollRange(animated)); } public float getScrollMin() { @@ -522,11 +522,17 @@ public boolean dismissSheet(Sheet sheet) { animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - sheet.getWindowView().setDrawingFromOverlay(false); View view = tab.webView != null ? tab.webView : tab.view2; if (view != null && tab.previewBitmap == null && tab.viewWidth > 0 && tab.viewHeight > 0) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - renderHardwareViewToBitmap(view, -tab.viewScroll, b -> tab.previewBitmap = b); + renderHardwareViewToBitmap(view, -tab.viewScroll, b -> { + tab.previewBitmap = b; + sheet.getWindowView().setDrawingFromOverlay(false); + sheet.release(); + }); + dismissingSheet = null; + invalidate(); + return; } else { tab.previewBitmap = Bitmap.createBitmap(tab.viewWidth, tab.viewHeight, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(tab.previewBitmap); @@ -534,6 +540,7 @@ public void onAnimationEnd(Animator animation) { view.draw(canvas); } } + sheet.getWindowView().setDrawingFromOverlay(false); sheet.release(); dismissingSheet = null; invalidate(); @@ -796,17 +803,10 @@ private void drawTabsPreview(Canvas canvas) { float alpha = 1f; float top, bottom, y; - if (SharedConfig.botTabs3DEffect) { - top = paddingTop + dp(6) * Math.min(5, position); - bottom = thisHeight - paddingBottom - height * .26f;// - dp(6) * Math.min(5, count - position); - y = top + (bottom - top) * scroll; - alpha = 1f; // Utilities.clamp(oscrollT * 4f + 1f, 1f, 0f); - } else { - top = paddingTop + dp(20) * ((float) Math.pow(1.1f, position) - 1f); - bottom = thisHeight - paddingBottom - height * .26f; - y = top + (bottom - top) * (float) (Math.pow(scrollT, 2)); - y = Math.min(y, thisHeight); - } + top = paddingTop + dp(6) * Math.min(5, position); + bottom = thisHeight - paddingBottom - height * .26f;// - dp(6) * Math.min(5, count - position); + y = top + (bottom - top) * scroll; + alpha = 1f; // Utilities.clamp(oscrollT * 4f + 1f, 1f, 0f); if (alpha <= 0) continue; @@ -831,65 +831,49 @@ private void drawTabsPreview(Canvas canvas) { canvas.save(); tab.clickBounds.set(rect2); - if (SharedConfig.botTabs3DEffect) { - Canvas tabCanvas = canvas; - tab.matrix.reset(); - - final int p = 0; - final float Sh = 1f; - tab.src[0] = rect2.left; - tab.src[1] = rect2.top; - tab.src[2] = rect2.right; - tab.src[3] = rect2.top; - tab.src[4] = rect2.right; - tab.src[5] = rect2.top + rect2.height() * Sh; - tab.src[6] = rect2.left; - tab.src[7] = rect2.top + rect2.height() * Sh; - - tab.dst[0] = rect2.left; - tab.dst[1] = rect2.top - dp(p); - tab.dst[2] = rect2.right; - tab.dst[3] = rect2.top - dp(p); - final float s1 = .83f, s2 = .6f; - tab.dst[4] = rect2.centerX() + rect2.width() / 2f * lerp(1f, s1, tabOpen * (1f - opening)); - tab.dst[5] = rect2.top - dp(p) + (rect2.height() * Sh + dp(p + p)) * lerp(1f, s2, tabOpen * (1f - opening)); - tab.dst[6] = rect2.centerX() - rect2.width() / 2f * lerp(1f, s1, tabOpen * (1f - opening)); - tab.dst[7] = rect2.top - dp(p) + (rect2.height() * Sh + dp(p + p)) * lerp(1f, s2, tabOpen * (1f - opening)); - - tab.matrix.setPolyToPoly(tab.src, 0, tab.dst, 0, 4); - tabCanvas.concat(tab.matrix); - - tab.draw( - tabCanvas, - rect2, - drawSimple, - tab.tabDrawable == openingTab ? 1f : lerp(tab.tabDrawable.getAlpha(), alpha, openProgress), - tab.tabDrawable == openingTab ? 1f : tabOpen * (1f - opening), - opening, - lerp(clamp01(position - count + 2),1f, clamp01((tabOpen - .1f) / .8f)) - ); - - if (openingSheet != null && tab.tabDrawable == openingTab) { - openingSheet.getWindowView().drawInto(canvas, rect2, 1f, rect2, opening, true); - } - canvas.restore(); - } else { - final float s = lerp( - 1f, - lerp( - lerp(1f, 1f - Utilities.clamp(count * .1f, .5f, .25f), 1f - scrollT), - Math.min(1, (float) Math.pow(0.7f, 1f - oscrollT)), - Utilities.clamp(count - 3, 1, 0) - ), - openProgress - ); - canvas.scale(s, s, rect2.centerX(), rect2.top); - scaleRect(tab.clickBounds, s, rect.centerX(), rect2.top); - - tab.draw(canvas, rect2, drawSimple, lerp(tab.tabDrawable.getAlpha(), 1f, openProgress), open, 0f, lerp(clamp01(position - count + 2), 1f, clamp01((open - .1f) / .8f))); - canvas.restore(); + Canvas tabCanvas = canvas; + tab.matrix.reset(); + + final int p = 0; + final float Sh = 1f; + tab.src[0] = rect2.left; + tab.src[1] = rect2.top; + tab.src[2] = rect2.right; + tab.src[3] = rect2.top; + tab.src[4] = rect2.right; + tab.src[5] = rect2.top + rect2.height() * Sh; + tab.src[6] = rect2.left; + tab.src[7] = rect2.top + rect2.height() * Sh; + + tab.dst[0] = rect2.left; + tab.dst[1] = rect2.top - dp(p); + tab.dst[2] = rect2.right; + tab.dst[3] = rect2.top - dp(p); + final float s1 = .83f, s2 = .6f; + tab.dst[4] = rect2.centerX() + rect2.width() / 2f * lerp(1f, s1, tabOpen * (1f - opening)); + tab.dst[5] = rect2.top - dp(p) + (rect2.height() * Sh + dp(p + p)) * lerp(1f, s2, tabOpen * (1f - opening)); + tab.dst[6] = rect2.centerX() - rect2.width() / 2f * lerp(1f, s1, tabOpen * (1f - opening)); + tab.dst[7] = rect2.top - dp(p) + (rect2.height() * Sh + dp(p + p)) * lerp(1f, s2, tabOpen * (1f - opening)); + + tab.matrix.setPolyToPoly(tab.src, 0, tab.dst, 0, 4); + tabCanvas.concat(tab.matrix); + + tab.draw( + tabCanvas, + rect2, + drawSimple, + tab.tabDrawable == openingTab ? 1f : lerp(tab.tabDrawable.getAlpha(), alpha, openProgress), + tab.tabDrawable == openingTab ? 1f : tabOpen * (1f - opening), + opening, + lerp(clamp01(position - count + 2),1f, clamp01((tabOpen - .1f) / .8f)) + ); + + if (openingSheet != null && tab.tabDrawable == openingTab) { + openingSheet.getWindowView().drawInto(canvas, rect2, 1f, rect2, opening, true); } + + canvas.restore(); } canvas.save(); if (gradientClip == null) { @@ -1019,10 +1003,7 @@ public void draw(Canvas canvas, RectF bounds, boolean simple, float alpha, float if (alpha <= 0) return; - float tabScaleY = 1f; - if (SharedConfig.botTabs3DEffect) { - tabScaleY = lerp(1f, 1.3f, expandProgress * (1f - openingProgress)); - } + float tabScaleY = lerp(1f, 1.3f, expandProgress * (1f - openingProgress)); final float tabTranslateY = openingProgress * (AndroidUtilities.statusBarHeight + ActionBar.getCurrentActionBarHeight() - dp(50)); canvas.save(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java index ea367c6be9..37b9c499c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -89,7 +89,7 @@ public class DrawerLayoutContainer extends FrameLayout { private float drawerPosition; private boolean drawerOpened; - private boolean allowDrawContent = true; + public boolean allowDrawContent = true; private boolean firstLayout = true; 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 9ac8e1e442..54506feba3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -3404,6 +3404,9 @@ public void run() { public static final int key_dialogEmptyText = colorsCount++; public static final int key_dialogSwipeRemove = colorsCount++; public static final int key_dialogReactionMentionBackground = colorsCount++; + public static final int key_dialogCardShadow = colorsCount++; + public static final int key_dialogGiftsBackground = colorsCount++; + public static final int key_dialogGiftsTabText = colorsCount++; public static final int key_windowBackgroundWhite = colorsCount++; public static final int key_windowBackgroundUnchecked = colorsCount++; @@ -3950,6 +3953,7 @@ public void run() { public static final int key_voipgroup_unmuteButton = colorsCount++; public static final int key_voipgroup_unmuteButton2 = colorsCount++; public static final int key_voipgroup_disabledButton = colorsCount++; + public static final int key_voipgroup_rtmpButton = colorsCount++; public static final int key_voipgroup_disabledButtonActive = colorsCount++; public static final int key_voipgroup_disabledButtonActiveScrolled = colorsCount++; public static final int key_voipgroup_connectingProgress = colorsCount++; @@ -4259,6 +4263,8 @@ public void run() { fallbackKeys.put(key_iv_backgroundGray, key_windowBackgroundGray); fallbackKeys.put(key_iv_navigationBackground, key_windowBackgroundGray); fallbackKeys.put(key_iv_ab_progress, key_featuredStickers_addButton); + fallbackKeys.put(key_dialogGiftsBackground, key_windowBackgroundGray); + fallbackKeys.put(key_dialogGiftsTabText, key_windowBackgroundWhiteGrayText2); fallbackKeys.put(key_chat_inQuote, key_featuredStickers_addButtonPressed); fallbackKeys.put(key_chat_outQuote, key_chat_outReplyLine); fallbackKeys.put(key_chat_outReplyLine2, key_chat_outReplyLine); @@ -4473,6 +4479,7 @@ public void run() { themeAccentExclusionKeys.add(key_voipgroup_leaveButtonScrolled); themeAccentExclusionKeys.add(key_voipgroup_connectingProgress); themeAccentExclusionKeys.add(key_voipgroup_disabledButton); + themeAccentExclusionKeys.add(key_voipgroup_rtmpButton); themeAccentExclusionKeys.add(key_voipgroup_disabledButtonActive); themeAccentExclusionKeys.add(key_voipgroup_disabledButtonActiveScrolled); themeAccentExclusionKeys.add(key_voipgroup_unmuteButton); 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 04456a9733..e05f7489a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java @@ -63,6 +63,9 @@ public static int[] createDefaultColors() { defaultColors[key_dialogEmptyText] = 0xff8c9094; defaultColors[key_dialogSwipeRemove] = 0xffe56555; defaultColors[key_dialogReactionMentionBackground] = 0xffF05459; + defaultColors[key_dialogCardShadow] = 0x30999999; + defaultColors[key_dialogGiftsBackground] = 0xffF5F6F7; + defaultColors[key_dialogGiftsTabText] = 0xFF56595C; defaultColors[key_windowBackgroundWhite] = 0xffffffff; defaultColors[key_windowBackgroundUnchecked] = 0xff9da7b1; @@ -696,6 +699,7 @@ public static int[] createDefaultColors() { defaultColors[key_voipgroup_leaveButtonScrolled] = 0x82D14D54; defaultColors[key_voipgroup_connectingProgress] = 0xff28BAFF; defaultColors[key_voipgroup_disabledButton] = 0xff1C2229; + defaultColors[key_voipgroup_rtmpButton] = 0xff2a3853; defaultColors[key_voipgroup_disabledButtonActive] = 0xff2C3A45; defaultColors[key_voipgroup_disabledButtonActiveScrolled] = 0x8277A1FC; defaultColors[key_voipgroup_unmuteButton] = 0xff539EF8; @@ -1365,6 +1369,7 @@ public static SparseArray createColorKeysMap() { colorKeysMap.put(key_voipgroup_unmuteButton, "voipgroup_unmuteButton"); colorKeysMap.put(key_voipgroup_unmuteButton2, "voipgroup_unmuteButton2"); colorKeysMap.put(key_voipgroup_disabledButton, "voipgroup_disabledButton"); + colorKeysMap.put(key_voipgroup_rtmpButton, "voipgroup_rtmpButton"); colorKeysMap.put(key_voipgroup_disabledButtonActive, "voipgroup_disabledButtonActive"); colorKeysMap.put(key_voipgroup_disabledButtonActiveScrolled, "voipgroup_disabledButtonActiveScrolled"); colorKeysMap.put(key_voipgroup_connectingProgress, "voipgroup_connectingProgress"); @@ -1550,6 +1555,9 @@ public static SparseArray createColorKeysMap() { colorKeysMap.put(key_iv_navigationBackground, "iv_navigationBackground"); colorKeysMap.put(key_iv_ab_progress, "iv_ab_progress"); colorKeysMap.put(key_reactionStarSelector, "reactionStarSelector"); + colorKeysMap.put(key_dialogCardShadow, "dialogCardShadow"); + colorKeysMap.put(key_dialogGiftsBackground, "dialogGiftsBackground"); + colorKeysMap.put(key_dialogGiftsTabText, "dialogGiftsTabText"); return colorKeysMap; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java index 42d75576ab..7e9b73ed5e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -66,7 +66,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { private int sortType; private boolean isChannel; private boolean disableSections; - private boolean isEmpty; + public boolean isEmpty; public boolean hasStories; public ArrayList userStories = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index 46381705c0..43bc02b95d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -1778,9 +1778,11 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int type = holder.getItemViewType(); if (type == 4) { StickerCell stickerCell = (StickerCell) holder.itemView; - StickerResult result = stickers.get(position); - stickerCell.setSticker(result.sticker, result.parent); - stickerCell.setClearsInputField(true); + if (position >= 0 && position < stickers.size()) { + StickerResult result = stickers.get(position); + stickerCell.setSticker(result.sticker, result.parent); + stickerCell.setClearsInputField(true); + } } else if (type == 3) { TextView textView = (TextView) holder.itemView; TLRPC.Chat chat = parentFragment.getCurrentChat(); @@ -1808,7 +1810,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (hasTop) { position--; } - ((ContextLinkCell) holder.itemView).setLink(searchResultBotContext.get(position), foundContextBot, contextMedia, position != searchResultBotContext.size() - 1, hasTop && position == 0, "gif".equals(searchingContextUsername)); + if (position >= 0 && position < searchResultBotContext.size()) { + ((ContextLinkCell) holder.itemView).setLink(searchResultBotContext.get(position), foundContextBot, contextMedia, position != searchResultBotContext.size() - 1, hasTop && position == 0, "gif".equals(searchingContextUsername)); + } } } else { MentionCell cell = (MentionCell) holder.itemView; @@ -1819,12 +1823,14 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (object instanceof TLRPC.Chat) { cell.setChat((TLRPC.Chat) object); } - } else if (searchResultHashtags != null) { + } else if (searchResultHashtags != null && position >= 0 && position < searchResultHashtags.size()) { cell.setText(searchResultHashtags.get(position)); - } else if (searchResultSuggestions != null) { + } else if (searchResultSuggestions != null && position >= 0 && position < searchResultSuggestions.size()) { cell.setEmojiSuggestion(searchResultSuggestions.get(position)); - } else if (searchResultCommands != null) { - cell.setBotCommand(searchResultCommands.get(position), searchResultCommandsHelp.get(position), searchResultCommandsUsers != null ? searchResultCommandsUsers.get(position) : null); + } else if (searchResultCommands != null && position >= 0 && position < searchResultCommands.size()) { + final String help = searchResultCommandsHelp != null && position >= 0 && position < searchResultCommandsHelp.size() ? searchResultCommandsHelp.get(position) : null; + final TLRPC.User user = searchResultCommandsUsers != null && position >= 0 && position < searchResultCommandsUsers.size() ? searchResultCommandsUsers.get(position) : null; + cell.setBotCommand(searchResultCommands.get(position), help, user); } cell.setDivider(USE_DIVIDERS && (isReversed ? position > 0 : position < getItemCount() - 1)); } 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 4924c9fde2..e11ceb970e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java @@ -174,7 +174,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { previewContainer.addView(previewBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); previewContainer.addView(greetingsView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 42, 18, 42, 18)); - titleEdit = new EditTextCell(context, getString(R.string.BusinessIntroTitleHint), false, getMessagesController().introTitleLengthLimit, resourceProvider) { + titleEdit = new EditTextCell(context, getString(R.string.BusinessIntroTitleHint), false, false, getMessagesController().introTitleLengthLimit, resourceProvider) { @Override protected void onTextChanged(CharSequence newText) { greetingsView.setPreview(titleEdit.getText().toString(), messageEdit.getText().toString()); @@ -193,7 +193,7 @@ protected void onFocusChanged(boolean focused) { titleEdit.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); titleEdit.setDivider(true); titleEdit.hideKeyboardOnEnter(); - messageEdit = new EditTextCell(context, getString(R.string.BusinessIntroMessageHint), true, getMessagesController().introDescriptionLengthLimit, resourceProvider) { + messageEdit = new EditTextCell(context, getString(R.string.BusinessIntroMessageHint), true, false, getMessagesController().introDescriptionLengthLimit, resourceProvider) { @Override protected void onTextChanged(CharSequence newText) { greetingsView.setPreview(titleEdit.getText().toString(), messageEdit.getText().toString()); 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 33c88a9e2f..f72ffe4a8a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -19,8 +19,12 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.CornerPathEffect; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PathEffect; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; @@ -49,6 +53,7 @@ import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; @@ -80,12 +85,15 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.AvatarSpan; import org.telegram.ui.ChannelAdminLogActivity; import org.telegram.ui.ChatBackgroundDrawable; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.ButtonBounce; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.LoadingDrawable; @@ -94,10 +102,14 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ScaleStateListAnimator; +import org.telegram.ui.Components.Text; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.spoilers.SpoilerEffect; +import org.telegram.ui.Gifts.GiftSheet; +import org.telegram.ui.GradientClip; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; import org.telegram.ui.ProfileActivity; @@ -114,6 +126,7 @@ import java.util.Map; import java.util.Objects; import java.util.Stack; +import java.util.concurrent.atomic.AtomicReference; public class ChatActionCell extends BaseCell implements DownloadController.FileDownloadProgressListener, NotificationCenter.NotificationCenterDelegate { private final static boolean USE_PREMIUM_GIFT_LOCAL_STICKER = false; @@ -140,7 +153,7 @@ public void didReceivedNotification(int id, int account, Object... args) { setSpoilersSuppressed(false); } else if (id == NotificationCenter.stopSpoilers) { setSpoilersSuppressed(true); - } else if (id == NotificationCenter.didUpdatePremiumGiftStickers) { + } else if (id == NotificationCenter.didUpdatePremiumGiftStickers || id == NotificationCenter.starGiftsLoaded) { MessageObject messageObject = currentMessageObject; if (messageObject != null) { setMessageObject(messageObject, true); @@ -219,6 +232,8 @@ default long getTopicId() { default boolean canDrawOutboundsContent() { return true; } + + default void forceUpdate(ChatActionCell cell, boolean anchorScroll) {} } public interface ThemeDelegate extends Theme.ResourcesProvider { @@ -229,6 +244,9 @@ public interface ThemeDelegate extends Theme.ResourcesProvider { private int TAG; private URLSpan pressedLink; + private SpoilerEffect spoilerPressed; + private boolean textPressed; + private boolean isSpoilerRevealing; private int currentAccount = UserConfig.selectedAccount; private ImageReceiver imageReceiver; private Drawable wallpaperPreviewDrawable; @@ -292,8 +310,47 @@ public interface ThemeDelegate extends Theme.ResourcesProvider { private int stickerSize; private int giftRectSize; private StaticLayout giftPremiumTitleLayout; - private int giftPremiumSubtitleWidth; private StaticLayout giftPremiumSubtitleLayout; + private boolean giftPremiumTextUncollapsed = false; + private boolean giftPremiumTextCollapsed = false; + private int giftPremiumTextCollapsedHeight; + private AnimatedFloat giftPremiumTextExpandedAnimated = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + + private GradientClip giftPremiumTextClip; + private TextLayout giftPremiumText; + private int giftPremiumTextMoreX, giftPremiumTextMoreY, giftPremiumTextMoreH; + private Text giftPremiumTextMore; + + class TextLayout { + public float x, y; + public int width; + public StaticLayout layout; + public TextPaint paint; + public List spoilers = new ArrayList<>(); + public final AtomicReference patchedLayout = new AtomicReference<>(); + public AnimatedEmojiSpan.EmojiGroupedSpans emoji; + + public void setText(CharSequence text, TextPaint textPaint, int width) { + this.paint = textPaint; + this.width = width; + layout = new StaticLayout(text, textPaint, width, Layout.Alignment.ALIGN_CENTER, 1.1f, 0.0f, false); + if (currentMessageObject == null || !currentMessageObject.isSpoilersRevealed) { + SpoilerEffect.addSpoilers(ChatActionCell.this, layout, -1, width, null, spoilers); + } else if (spoilers != null) { + spoilers.clear(); + } + attach(); + } + + public void attach() { + emoji = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatActionCell.this, false, emoji, layout); + } + + public void detach() { + AnimatedEmojiSpan.release(ChatActionCell.this, emoji); + } + } + private StaticLayout giftPremiumButtonLayout; private boolean buttonClickableAsImage = true; TextPaint settingWallpaperPaint; @@ -303,6 +360,7 @@ public interface ThemeDelegate extends Theme.ResourcesProvider { private float giftPremiumButtonWidth; private TextPaint giftTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private TextPaint giftTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private TextPaint giftSubtitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private TLRPC.Document giftSticker; @@ -345,6 +403,12 @@ public interface ThemeDelegate extends Theme.ResourcesProvider { } }; + private boolean giftRibbonPaintFilterDark; + private ColorMatrixColorFilter giftRibbonPaintFilter; + private CornerPathEffect giftRibbonPaintEffect; + private Path giftRibbonPath; + private Text giftRibbonText; + private View rippleView; private Path starsPath = new Path(); @@ -367,6 +431,7 @@ public ChatActionCell(Context context, boolean canDrawInParent, Theme.ResourcesP giftTitlePaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics())); giftSubtitlePaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics())); + giftTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics())); rippleView = new View(context); rippleView.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(Color.BLACK, .1f), Theme.RIPPLE_MASK_ROUNDRECT_6DP, dp(16))); @@ -462,6 +527,12 @@ public void setMessageObject(MessageObject messageObject, boolean force) { hasReplyMessage = messageObject.replyMessageObject != null; DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); previousWidth = 0; + isSpoilerRevealing = false; + if (giftPremiumText != null && messageIdChanged) { + giftPremiumText.detach(); + giftPremiumText = null; + giftPremiumTextUncollapsed = false; + } imageReceiver.setAutoRepeatCount(0); imageReceiver.clearDecorators(); if (messageObject.type != MessageObject.TYPE_ACTION_WALLPAPER) { @@ -587,82 +658,93 @@ public void setMessageObject(MessageObject messageObject, boolean force) { imageReceiver.setDelegate(giftStickerDelegate); imageReceiver.setImageBitmap(new RLottieDrawable(R.raw.premium_gift, messageObject.getId() + "_" + R.raw.premium_gift, dp(160), dp(160))); } else { - TLRPC.TL_messages_stickerSet set; + TLRPC.TL_messages_stickerSet set = null; TLRPC.Document document = null; - - String packName = UserConfig.getInstance(currentAccount).premiumGiftsStickerPack; - if (packName == null) { - MediaDataController.getInstance(currentAccount).checkPremiumGiftStickers(); - return; - } - set = MediaDataController.getInstance(currentAccount).getStickerSetByName(packName); - if (set == null) { - set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(packName); - } - if (set != null) { - int months = messageObject.messageOwner.action.months; - String monthsEmoticon; - if (messageObject.type == MessageObject.TYPE_GIFT_STARS) { - final long stars; - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftStars) { - stars = ((TLRPC.TL_messageActionGiftStars) messageObject.messageOwner.action).stars; - } else { - stars = ((TLRPC.TL_messageActionPrizeStars) messageObject.messageOwner.action).stars; - } - String emoji; - if (stars <= 1000) { - emoji = "2⃣"; - } else if (stars < 2500) { - emoji = "3⃣"; - } else { - emoji = "4⃣"; - } - for (int i = 0; i < set.packs.size(); ++i) { - TLRPC.TL_stickerPack pack = set.packs.get(i); - if (TextUtils.equals(pack.emoticon, emoji) && !pack.documents.isEmpty()) { - long documentId = pack.documents.get(0); - for (int j = 0; j < set.documents.size(); ++j) { - TLRPC.Document d = set.documents.get(j); - if (d != null && d.id == documentId) { - document = d; - break; + String packName = null; + Object parentObject = null; + + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift) { + parentObject = messageObject; + final TLRPC.TL_messageActionStarGift action = (TLRPC.TL_messageActionStarGift) messageObject.messageOwner.action; + if (action.gift != null) { + document = action.gift.sticker; + } + } else { + packName = UserConfig.getInstance(currentAccount).premiumGiftsStickerPack; + if (packName == null) { + MediaDataController.getInstance(currentAccount).checkPremiumGiftStickers(); + return; + } + set = MediaDataController.getInstance(currentAccount).getStickerSetByName(packName); + if (set == null) { + set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(packName); + } + if (set != null) { + parentObject = set; + int months = messageObject.messageOwner.action.months; + String monthsEmoticon; + if (messageObject.type == MessageObject.TYPE_GIFT_STARS) { + final long stars; + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftStars) { + stars = ((TLRPC.TL_messageActionGiftStars) messageObject.messageOwner.action).stars; + } else { + stars = ((TLRPC.TL_messageActionPrizeStars) messageObject.messageOwner.action).stars; + } + String emoji; + if (stars <= 1000) { + emoji = "2⃣"; + } else if (stars < 2500) { + emoji = "3⃣"; + } else { + emoji = "4⃣"; + } + for (int i = 0; i < set.packs.size(); ++i) { + TLRPC.TL_stickerPack pack = set.packs.get(i); + if (TextUtils.equals(pack.emoticon, emoji) && !pack.documents.isEmpty()) { + long documentId = pack.documents.get(0); + for (int j = 0; j < set.documents.size(); ++j) { + TLRPC.Document d = set.documents.get(j); + if (d != null && d.id == documentId) { + document = d; + break; + } } + break; } - break; } - } - } else { - if (USE_PREMIUM_GIFT_MONTHS_AS_EMOJI_NUMBERS) { - StringBuilder monthsEmoticonBuilder = new StringBuilder(); - while (months > 0) { - monthsEmoticonBuilder.insert(0, (months % 10) + "\u20E3"); - months /= 10; - } - monthsEmoticon = monthsEmoticonBuilder.toString(); } else { - monthsEmoticon = monthsToEmoticon.get(months); - } - for (TLRPC.TL_stickerPack pack : set.packs) { - if (Objects.equals(pack.emoticon, monthsEmoticon)) { - for (long id : pack.documents) { - for (TLRPC.Document doc : set.documents) { - if (doc.id == id) { - document = doc; + if (USE_PREMIUM_GIFT_MONTHS_AS_EMOJI_NUMBERS) { + StringBuilder monthsEmoticonBuilder = new StringBuilder(); + while (months > 0) { + monthsEmoticonBuilder.insert(0, (months % 10) + "\u20E3"); + months /= 10; + } + monthsEmoticon = monthsEmoticonBuilder.toString(); + } else { + monthsEmoticon = monthsToEmoticon.get(months); + } + for (TLRPC.TL_stickerPack pack : set.packs) { + if (Objects.equals(pack.emoticon, monthsEmoticon)) { + for (long id : pack.documents) { + for (TLRPC.Document doc : set.documents) { + if (doc.id == id) { + document = doc; + break; + } + } + if (document != null) { break; } } - if (document != null) { - break; - } } - } - if (document != null) { - break; + if (document != null) { + break; + } } } - } - if (document == null && !set.documents.isEmpty()) { - document = set.documents.get(0); + if (document == null && !set.documents.isEmpty()) { + document = set.documents.get(0); + } } } @@ -679,10 +761,12 @@ public void setMessageObject(MessageObject messageObject, boolean force) { break; } } - SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.3f); - imageReceiver.setAutoRepeat(0); - imageReceiver.setImage(ImageLocation.getForDocument(document), String.format(Locale.US, "%d_%d_nr_messageId=%d", 160, 160, messageObject.stableId), svgThumb, "tgs", set, 1); - } else { + if (messageIdChanged || messageObject == null || messageObject.type != MessageObject.TYPE_GIFT_PREMIUM) { + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.3f); + imageReceiver.setAutoRepeat(0); + imageReceiver.setImage(ImageLocation.getForDocument(document), String.format(Locale.US, "%d_%d_nr_messageId=%d", 160, 160, messageObject.stableId), svgThumb, "tgs", parentObject, 1); + } + } else if (packName != null) { MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, set == null); } } @@ -798,8 +882,12 @@ protected void onDetachedFromWindow() { setStarsPaused(true); wasLayout = false; AnimatedEmojiSpan.release(this, animatedEmojiStack); + if (giftPremiumText != null) { + giftPremiumText.detach(); + } NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.didUpdatePremiumGiftStickers); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.starGiftsLoaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.diceStickersDidLoad); avatarStoryParams.onDetachFromWindow(); } @@ -811,7 +899,11 @@ protected void onAttachedToWindow() { setStarsPaused(false); animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, canDrawInParent && (delegate != null && !delegate.canDrawOutboundsContent()), animatedEmojiStack, textLayout); + if (giftPremiumText != null) { + giftPremiumText.attach(); + } NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didUpdatePremiumGiftStickers); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starGiftsLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.diceStickersDidLoad); if (currentMessageObject != null && currentMessageObject.type == MessageObject.TYPE_SUGGEST_PHOTO) { @@ -855,6 +947,13 @@ public boolean onTouchEvent(MotionEvent event) { imagePressed = true; result = true; } + if (giftPremiumText != null && giftPremiumTextCollapsed) { + AndroidUtilities.rectTmp.set(giftPremiumText.x, giftPremiumText.y, giftPremiumText.x + giftPremiumText.layout.getWidth(), giftPremiumText.y + giftPremiumText.layout.getHeight()); + if (AndroidUtilities.rectTmp.contains(x, y)) { + textPressed = true; + result = true; + } + } if (isButtonLayout(messageObject) && giftPremiumButtonLayout != null && (giftButtonRect.contains(x, y) || buttonClickableAsImage && backgroundRect.contains(x, y))) { rippleView.setPressed(giftButtonPressed = true); bounce.setPressed(true); @@ -868,7 +967,41 @@ public boolean onTouchEvent(MotionEvent event) { if (event.getAction() != MotionEvent.ACTION_MOVE) { cancelCheckLongPress(); } - if (giftButtonPressed) { + if (textPressed) { + switch (event.getAction()) { + case MotionEvent.ACTION_UP: + rippleView.setPressed(textPressed = false); + bounce.setPressed(false); + if (giftPremiumTextCollapsed && !giftPremiumTextUncollapsed && giftPremiumText != null) { + int dy = giftPremiumText.layout.getHeight() - giftPremiumTextCollapsedHeight; + giftPremiumTextUncollapsed = true; + if (delegate != null) { + delegate.forceUpdate(this, false); + if (getParent() instanceof RecyclerListView) { + ((RecyclerListView) getParent()).smoothScrollBy(0, dy + dp(24)); + } + } + return true; + } + break; + case MotionEvent.ACTION_CANCEL: + textPressed = false; + bounce.setPressed(false); + break; + case MotionEvent.ACTION_MOVE: + if (giftPremiumText == null || !giftPremiumTextCollapsed) { + textPressed = false; + result = true; + } else { + AndroidUtilities.rectTmp.set(giftPremiumText.x, giftPremiumText.y, giftPremiumText.x + giftPremiumText.layout.getWidth(), giftPremiumText.y + giftPremiumText.layout.getHeight()); + if (!AndroidUtilities.rectTmp.contains(x, y)) { + textPressed = false; + result = true; + } + } + break; + } + } else if (giftButtonPressed) { switch (event.getAction()) { case MotionEvent.ACTION_UP: imagePressed = false; @@ -912,6 +1045,17 @@ public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: imagePressed = false; + if (giftPremiumTextCollapsed && !giftPremiumTextUncollapsed && giftPremiumText != null) { + int dy = giftPremiumText.layout.getHeight() - giftPremiumTextCollapsedHeight; + giftPremiumTextUncollapsed = true; + if (delegate != null) { + delegate.forceUpdate(this, false); + if (getParent() instanceof RecyclerListView) { + ((RecyclerListView) getParent()).smoothScrollBy(0, dy + dp(16)); + } + } + return true; + } if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL) { openPremiumGiftChannel(); } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { @@ -951,33 +1095,64 @@ public boolean onTouchEvent(MotionEvent event) { } } if (!result) { - if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) { - if (textLayout != null && x >= textX && y >= textY && x <= textX + textWidth && y <= textY + textHeight) { - y -= textY; - x -= textXLeft; - - final int line = textLayout.getLineForVertical((int) y); - final int off = textLayout.getOffsetForHorizontal(line, x); - final float left = textLayout.getLineLeft(line); - if (left <= x && left + textLayout.getLineWidth(line) >= x && messageObject.messageText instanceof Spannable) { - Spannable buffer = (Spannable) messageObject.messageText; - URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); - - if (link.length != 0) { + if (event.getAction() == MotionEvent.ACTION_DOWN || (pressedLink != null || spoilerPressed != null) && event.getAction() == MotionEvent.ACTION_UP) { + if (giftPremiumText != null && giftPremiumText.spoilers != null && !giftPremiumText.spoilers.isEmpty() && !isSpoilerRevealing) { + for (SpoilerEffect eff : giftPremiumText.spoilers) { + if (eff.getBounds().contains((int) (x - giftPremiumText.x), (int) (y - giftPremiumText.y))) { + pressedLink = null; if (event.getAction() == MotionEvent.ACTION_DOWN) { - pressedLink = link[0]; + spoilerPressed = eff; result = true; } else { - if (link[0] == pressedLink) { - openLink(pressedLink); + if (eff == spoilerPressed) { + isSpoilerRevealing = true; + spoilerPressed.setOnRippleEndCallback(() -> post(() -> { + isSpoilerRevealing = false; + getMessageObject().isSpoilersRevealed = true; + if (giftPremiumText.spoilers != null) { + giftPremiumText.spoilers.clear(); + } + invalidate(); + })); + float width = giftPremiumText.layout.getWidth(), height = giftPremiumText.layout.getHeight(); + float rad = (float) Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); + spoilerPressed.startRipple((int) (x - giftPremiumText.x), (int) (y - giftPremiumText.y), rad); + invalidate(); + } + result = true; + } + break; + } + } + } + if (!result && textLayout != null && x >= textX && y >= textY && x <= textX + textWidth && y <= textY + textHeight) { + y -= textY; + x -= textXLeft; + + if (!result) { + final int line = textLayout.getLineForVertical((int) y); + final int off = textLayout.getOffsetForHorizontal(line, x); + final float left = textLayout.getLineLeft(line); + if (left <= x && left + textLayout.getLineWidth(line) >= x && messageObject.messageText instanceof Spannable) { + Spannable buffer = (Spannable) messageObject.messageText; + URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); + + if (link.length != 0) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + pressedLink = link[0]; result = true; + } else { + if (link[0] == pressedLink) { + openLink(pressedLink); + result = true; + } } + } else { + pressedLink = null; } } else { pressedLink = null; } - } else { - pressedLink = null; } } else { pressedLink = null; @@ -1035,6 +1210,10 @@ private void openStarsGiftTransaction() { StarsIntroActivity.showTransactionSheet(getContext(), currentAccount, currentMessageObject.messageOwner.date, currentMessageObject.messageOwner.from_id, currentMessageObject.messageOwner.peer_id, (TLRPC.TL_messageActionGiftStars) currentMessageObject.messageOwner.action, avatarStoryParams.resourcesProvider); } else if (currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionPrizeStars) { StarsIntroActivity.showTransactionSheet(getContext(), currentAccount, currentMessageObject.messageOwner.date, currentMessageObject.messageOwner.from_id, currentMessageObject.messageOwner.peer_id, (TLRPC.TL_messageActionPrizeStars) currentMessageObject.messageOwner.action, avatarStoryParams.resourcesProvider); + } else if (currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift) { + final TLRPC.TL_messageActionStarGift action = (TLRPC.TL_messageActionStarGift) currentMessageObject.messageOwner.action; + if (action.forceIn) return; + StarsIntroActivity.showActionGiftSheet(getContext(), currentAccount, currentMessageObject.getDialogId(), currentMessageObject.isOutOwner(), currentMessageObject.messageOwner.date, currentMessageObject.getId(), action, themeDelegate); } } @@ -1183,23 +1362,38 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int imageSize = getImageSize(messageObject); float y; if (isNewStyleButtonLayout()) { - y = textY + textHeight + dp(4) + dp(16) * 2 + imageSize + giftPremiumSubtitleLayout.getHeight() + dp(4); + y = textY + textHeight + dp(4) + dp(16) * 2 + imageSize + (giftPremiumText == null ? 0 : giftPremiumText.layout.getHeight() + dp(4)); } else { - y = textY + textHeight + giftRectSize * 0.075f + imageSize + dp(4) + dp(4) + giftPremiumSubtitleLayout.getHeight(); + y = textY + textHeight + giftRectSize * 0.075f + imageSize + dp(4) + (giftPremiumText == null ? 0 : giftPremiumText.layout.getHeight() + dp(4)); } giftPremiumAdditionalHeight = 0; if (giftPremiumTitleLayout != null) { y += giftPremiumTitleLayout.getHeight(); + if (giftPremiumTitleLayout.getLineCount() > 1) { + giftPremiumAdditionalHeight += giftPremiumTitleLayout.getHeight() - giftPremiumTitleLayout.getLineTop(1); + } y += dp(isGiftChannel ? 6 : 0); + if (giftPremiumSubtitleLayout != null) { + y += giftPremiumSubtitleLayout.getHeight() + dp(9); + } } else { y -= dp(12); giftPremiumAdditionalHeight -= dp(30); } - if (currentMessageObject.type == MessageObject.TYPE_GIFT_STARS) { - giftPremiumAdditionalHeight += giftPremiumSubtitleLayout.getHeight() - dp(20); - } else if (giftPremiumSubtitleLayout.getLineCount() > 2) { - giftPremiumAdditionalHeight += (giftPremiumSubtitleLayout.getLineBottom(0) - giftPremiumSubtitleLayout.getLineTop(0)) * giftPremiumSubtitleLayout.getLineCount() - 2; + int giftTextHeight = giftPremiumText == null ? 0 : giftPremiumText.layout.getHeight(); + if (giftPremiumText == null) { + giftPremiumAdditionalHeight = 0; + } else if (giftPremiumSubtitleLayout != null) { + giftPremiumAdditionalHeight += giftTextHeight + dp(10); + } else if (currentMessageObject.type == MessageObject.TYPE_GIFT_PREMIUM || currentMessageObject.isStarGiftAction()) { + giftPremiumAdditionalHeight += giftTextHeight - dp(giftPremiumButtonLayout == null ? 0 : 10); + } else if (currentMessageObject.type == MessageObject.TYPE_GIFT_STARS) { + giftPremiumAdditionalHeight += giftTextHeight - dp(20); + } else if (giftPremiumTextCollapsed) { + giftPremiumAdditionalHeight += giftTextHeight; + } else if (giftPremiumText.layout.getLineCount() > 2) { + giftPremiumAdditionalHeight += (giftPremiumText.layout.getLineBottom(0) - giftPremiumText.layout.getLineTop(0)) * giftPremiumText.layout.getLineCount() - 2; } giftPremiumAdditionalHeight -= dp(isGiftChannel ? 14 : 0); @@ -1210,11 +1404,18 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (giftPremiumButtonLayout != null) { y += (h - y - (giftPremiumButtonLayout != null ? giftPremiumButtonLayout.getHeight() : 0) - dp(8)) / 2f; + if (currentMessageObject.isStarGiftAction()) { + y += dp(4); + } float rectX = (previousWidth - giftPremiumButtonWidth) / 2f; giftButtonRect.set(rectX - dp(18), y - dp(8), rectX + giftPremiumButtonWidth + dp(18), y + (giftPremiumButtonLayout != null ? giftPremiumButtonLayout.getHeight() : 0) + dp(8)); } else { additionalHeight -= dp(40); giftPremiumAdditionalHeight -= dp(40); + if (currentMessageObject != null && currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift) { + additionalHeight -= dp(8); + giftPremiumAdditionalHeight -= dp(8); + } } int sizeInternal = getMeasuredWidth() << 16 + getMeasuredHeight(); starParticlesDrawable.rect.set(giftButtonRect); @@ -1228,12 +1429,18 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { exactlyHeight = textY + textHeight + dp(4); backgroundRectHeight = 0; backgroundRectHeight += dp(16) * 2 + imageSize; - backgroundRectHeight += giftPremiumSubtitleLayout.getHeight(); + if (giftPremiumSubtitleLayout != null) { + backgroundRectHeight += giftPremiumSubtitleLayout.getHeight() + dp(10); + } + backgroundRectHeight += giftTextHeight; + float rectX = (previousWidth - giftPremiumButtonWidth) / 2f; if (giftPremiumButtonLayout != null) { backgroundButtonTop = exactlyHeight + backgroundRectHeight + dp(10); - float rectX = (previousWidth - giftPremiumButtonWidth) / 2f; giftButtonRect.set(rectX - dp(18), backgroundButtonTop, rectX + giftPremiumButtonWidth + dp(18), backgroundButtonTop + giftPremiumButtonLayout.getHeight() + dp(8) * 2); backgroundRectHeight += dp(10) + giftButtonRect.height(); + } else { + giftButtonRect.set(rectX - dp(18), backgroundButtonTop, rectX + giftPremiumButtonWidth + dp(18), backgroundButtonTop + dp(17) + dp(8) * 2); + backgroundRectHeight += dp(17); } backgroundRectHeight += dp(16); exactlyHeight += backgroundRectHeight; @@ -1309,8 +1516,54 @@ private void buildLayout() { stars = ((TLRPC.TL_messageActionGiftStars) messageObject.messageOwner.action).stars; createGiftPremiumLayouts( formatPluralStringComma("ActionGiftStarsTitle", (int) stars), + null, AndroidUtilities.replaceTags(currentMessageObject.isOutOwner() ? formatString(R.string.ActionGiftStarsSubtitle, UserObject.getForcedFirstName(user)) : getString(R.string.ActionGiftStarsSubtitleYou)), - getString(R.string.ActionGiftStarsView), + false, getString(R.string.ActionGiftStarsView), + null, giftRectSize, + true + ); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift) { + final TLRPC.TL_messageActionStarGift action = (TLRPC.TL_messageActionStarGift) messageObject.messageOwner.action; + stars = action.convert_stars; + final long userId = messageObject.getFromChatId(); + final SpannableStringBuilder sb = new SpannableStringBuilder(); + final TLRPC.User userReceiver = MessagesController.getInstance(currentAccount).getUser(userId); + sb.append(LocaleController.getString(R.string.Gift2ActionTitle)).append(" "); + if (userReceiver != null && userReceiver.photo != null) { + sb.append("a "); + final AvatarSpan avatarSpan = new AvatarSpan(this, currentAccount, 18); + avatarSpan.setUser(userReceiver); + sb.setSpan(avatarSpan, sb.length() - 2, sb.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + sb.append(UserObject.getForcedFirstName(userReceiver)); + CharSequence title; + if (action.message != null && !TextUtils.isEmpty(action.message.text)) { + title = new SpannableStringBuilder(action.message.text); + giftTextPaint.setTextSize(dp(13)); + MessageObject.addEntitiesToText(title, action.message.entities, false, false, true, true); + title = Emoji.replaceEmoji(title, giftTextPaint.getFontMetricsInt(), false, null); + title = MessageObject.replaceAnimatedEmoji(title, action.message.entities, giftTextPaint.getFontMetricsInt()); + } else if (messageObject.isOutOwner()) { + title = AndroidUtilities.replaceTags(formatPluralStringComma("Gift2ActionOutInfo", (int) stars, UserObject.getForcedFirstName(user))); + } else { + if (action.converted) { + title = formatPluralStringComma("Gift2ActionConvertedInfo", (int) stars); + } else if (action.saved) { + title = getString(R.string.Gift2ActionSavedInfo); + } else { + title = formatPluralStringComma("Gift2ActionInfo", (int) stars); + } + } + CharSequence ribbon = null; + if (action.gift != null && action.gift.limited) { + ribbon = LocaleController.formatString(R.string.Gift2Limited1OfRibbon, action.gift.availability_total > 1500 ? AndroidUtilities.formatWholeNumber(action.gift.availability_total, 0) : action.gift.availability_total); + } + createGiftPremiumLayouts( + sb, + null, + title, + false, messageObject.isOutOwner() && !action.forceIn ? null : getString(R.string.ActionGiftStarsView), + ribbon, giftRectSize, true ); @@ -1318,8 +1571,10 @@ private void buildLayout() { stars = ((TLRPC.TL_messageActionPrizeStars) messageObject.messageOwner.action).stars; createGiftPremiumLayouts( getString(R.string.ActionStarGiveawayPrizeTitle), + null, currentMessageObject.messageText, - getString(R.string.ActionGiftStarsView), + false, getString(R.string.ActionGiftStarsView), + null, giftRectSize, true ); @@ -1328,8 +1583,26 @@ private void buildLayout() { textY = 0; } } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { + int months; + TLRPC.TL_textWithEntities textWithEntities = null; + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { + textWithEntities = ((TLRPC.TL_messageActionGiftPremium) messageObject.messageOwner.action).message; + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { + textWithEntities = ((TLRPC.TL_messageActionGiftCode) messageObject.messageOwner.action).message; + } + CharSequence messageText = null; + if (textWithEntities != null && !TextUtils.isEmpty(textWithEntities.text)) { + messageText = new SpannableStringBuilder(textWithEntities.text); + giftTextPaint.setTextSize(dp(13)); + MessageObject.addEntitiesToText(messageText, textWithEntities.entities, false, false, true, true); + messageText = Emoji.replaceEmoji(messageText, giftTextPaint.getFontMetricsInt(), false, null); + messageText = MessageObject.replaceAnimatedEmoji(messageText, textWithEntities.entities, giftTextPaint.getFontMetricsInt()); + } + if (messageText == null) { + messageText = LocaleController.getString(R.string.ActionGiftPremiumText); + } String actionName = getString(isGiftCode() && !isSelfGiftCode() ? R.string.GiftPremiumUseGiftBtn : R.string.ActionGiftPremiumView); - createGiftPremiumLayouts(getString(R.string.ActionGiftPremiumTitle), formatString(R.string.ActionGiftPremiumSubtitle, LocaleController.formatPluralString("Months", messageObject.messageOwner.action.months)), actionName, giftRectSize, true); + createGiftPremiumLayouts(formatPluralStringComma("ActionGiftPremiumTitle2", messageObject.messageOwner.action.months), null, messageText, true, actionName, null, giftRectSize, false); } else if (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO) { TLRPC.TL_messageActionSuggestProfilePhoto actionSuggestProfilePhoto = (TLRPC.TL_messageActionSuggestProfilePhoto) messageObject.messageOwner.action; String description; @@ -1355,7 +1628,7 @@ private void buildLayout() { } else { action = getString(R.string.ViewPhotoAction); } - createGiftPremiumLayouts(null, description, action, giftRectSize, true); + createGiftPremiumLayouts(null, null, description, false, action, null, giftRectSize, true); textLayout = null; textHeight = 0; textY = 0; @@ -1376,7 +1649,7 @@ private void buildLayout() { description = messageObject.messageText; action = getString(R.string.ViewWallpaperAction); } - createGiftPremiumLayouts(null, description, action, giftRectSize, actionClickableAsImage); + createGiftPremiumLayouts(null, null, description, false, action, null, giftRectSize, actionClickableAsImage); textLayout = null; textHeight = 0; textY = 0; @@ -1393,7 +1666,7 @@ private void buildLayout() { } action = getString(R.string.StoryMentionedAction); - createGiftPremiumLayouts(null, description, action, giftRectSize, true); + createGiftPremiumLayouts(null, null, description, false, action, null, giftRectSize, true); textLayout = null; textHeight = 0; textY = 0; @@ -1405,7 +1678,7 @@ private void createGiftPremiumChannelLayouts() { int width = giftRectSize; width -= dp(16); giftTitlePaint.setTextSize(dp(14)); - giftSubtitlePaint.setTextSize(dp(13)); + giftTextPaint.setTextSize(dp(13)); TLRPC.TL_messageActionGiftCode gifCodeAction = (TLRPC.TL_messageActionGiftCode) currentMessageObject.messageOwner.action; int months = gifCodeAction.months; TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-DialogObject.getPeerDialogId(gifCodeAction.boost_peer)); @@ -1437,18 +1710,25 @@ private void createGiftPremiumChannelLayouts() { SpannableStringBuilder titleBuilder = SpannableStringBuilder.valueOf(title); titleBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, titleBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); giftPremiumTitleLayout = new StaticLayout(titleBuilder, giftTitlePaint, width, Layout.Alignment.ALIGN_CENTER, 1.1f, 0.0f, false); + giftPremiumSubtitleLayout = null; - giftPremiumSubtitleWidth = width; - giftPremiumSubtitleLayout = new StaticLayout(subtitle, giftSubtitlePaint, width, Layout.Alignment.ALIGN_CENTER, 1.1f, 0.0f, false); + if (giftPremiumText != null) { + giftPremiumText.detach(); + } + giftPremiumText = new TextLayout(); + giftPremiumText.setText(subtitle, giftTextPaint, width); SpannableStringBuilder buttonBuilder = SpannableStringBuilder.valueOf(btnText); buttonBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, buttonBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + giftPremiumTextCollapsed = false; + giftPremiumTextCollapsedHeight = 0; + giftPremiumTextMore = null; giftPremiumButtonLayout = new StaticLayout(buttonBuilder, (TextPaint) getThemedPaint(Theme.key_paint_chatActionText), width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); buttonClickableAsImage = true; giftPremiumButtonWidth = measureLayoutWidth(giftPremiumButtonLayout); } - private void createGiftPremiumLayouts(CharSequence title, CharSequence subtitle, CharSequence button, int width, boolean buttonClickableAsImage) { + private void createGiftPremiumLayouts(CharSequence title, CharSequence subtitle, CharSequence text, boolean allowCollapsing, CharSequence button, CharSequence ribbon, int width, boolean buttonClickableAsImage) { width -= dp(16); if (currentMessageObject != null && currentMessageObject.type == MessageObject.TYPE_GIFT_STARS) { width -= dp(16); @@ -1465,33 +1745,81 @@ private void createGiftPremiumLayouts(CharSequence title, CharSequence subtitle, } else { giftPremiumTitleLayout = null; } - if (currentMessageObject != null && (isNewStyleButtonLayout() || currentMessageObject.type == MessageObject.TYPE_GIFT_STARS)) { + if (subtitle != null) { giftSubtitlePaint.setTextSize(dp(13)); + giftPremiumSubtitleLayout = new StaticLayout(subtitle, giftSubtitlePaint, width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + } else { + giftPremiumSubtitleLayout = null; + } + if (currentMessageObject != null && (isNewStyleButtonLayout() || currentMessageObject.type == MessageObject.TYPE_GIFT_STARS || currentMessageObject.type == MessageObject.TYPE_GIFT_PREMIUM)) { + giftTextPaint.setTextSize(dp(13)); } else { - giftSubtitlePaint.setTextSize(dp(15)); + giftTextPaint.setTextSize(dp(15)); } - int subtitleWidth = giftPremiumSubtitleWidth = width; + int textWidth = width - dp(12); if (currentMessageObject != null && (currentMessageObject.type == MessageObject.TYPE_ACTION_WALLPAPER && currentMessageObject.getDialogId() >= 0)) { - final int recommendedWidthForTwoLines = HintView2.cutInFancyHalf(subtitle, giftSubtitlePaint); - if (recommendedWidthForTwoLines < subtitleWidth && recommendedWidthForTwoLines > subtitleWidth / 5f) { - subtitleWidth = recommendedWidthForTwoLines; + final int recommendedWidthForTwoLines = HintView2.cutInFancyHalf(text, giftTextPaint); + if (recommendedWidthForTwoLines < textWidth && recommendedWidthForTwoLines > textWidth / 5f) { + textWidth = recommendedWidthForTwoLines; + } + } + if (text == null) { + if (giftPremiumText != null) { + giftPremiumText.detach(); + giftPremiumText = null; + } + giftPremiumTextCollapsed = false; + } else { + if (giftPremiumText == null) { + giftPremiumText = new TextLayout(); + } + try { + text = Emoji.replaceEmoji(text, giftTextPaint.getFontMetricsInt(), false); + } catch (Exception ignore) { + } + giftPremiumText.setText(text, giftTextPaint, textWidth); + if (allowCollapsing && giftPremiumText.layout.getLineCount() > 3) { + giftPremiumTextCollapsed = !giftPremiumTextUncollapsed; + giftPremiumTextCollapsedHeight = giftPremiumText.layout.getLineBottom(2); + giftPremiumTextMore = new Text(LocaleController.getString(R.string.Gift2CaptionMore), giftTextPaint.getTextSize() / AndroidUtilities.density, AndroidUtilities.bold()); + giftPremiumTextMoreY = giftPremiumText.layout.getLineBottom(2); + giftPremiumTextMoreH = giftPremiumTextMoreY - giftPremiumText.layout.getLineTop(2); + giftPremiumTextMoreX = (int) giftPremiumText.layout.getLineRight(2); + } else { + giftPremiumTextCollapsed = false; + giftPremiumTextExpandedAnimated.set(true, true); + giftPremiumTextCollapsedHeight = 0; + } + if (giftPremiumTextCollapsed) { + int index = giftPremiumText.layout.getLineEnd(2) - 1; + giftPremiumText.setText(text.subSequence(0, index), giftTextPaint, textWidth); } } - try { - subtitle = Emoji.replaceEmoji(subtitle, giftSubtitlePaint.getFontMetricsInt(), false); - } catch (Exception ignore) {} - giftPremiumSubtitleLayout = new StaticLayout(subtitle, giftSubtitlePaint, subtitleWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, dp(1.66f), false); if (button != null) { SpannableStringBuilder buttonBuilder = SpannableStringBuilder.valueOf(button); buttonBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, buttonBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); giftPremiumButtonLayout = new StaticLayout(buttonBuilder, (TextPaint) getThemedPaint(Theme.key_paint_chatActionText), width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); - this.buttonClickableAsImage = buttonClickableAsImage; + this.buttonClickableAsImage = buttonClickableAsImage && !giftPremiumTextCollapsed; giftPremiumButtonWidth = measureLayoutWidth(giftPremiumButtonLayout); } else { giftPremiumButtonLayout = null; this.buttonClickableAsImage = false; giftPremiumButtonWidth = 0; } + if (ribbon != null) { + if (giftRibbonPaintEffect == null) { + giftRibbonPaintEffect = new CornerPathEffect(dp(5)); + } + if (giftRibbonPath == null) { + giftRibbonPath = new Path(); + GiftSheet.Ribbon.fillRibbonPath(giftRibbonPath, 1.35f); + } + giftRibbonText = new Text(ribbon, 11, AndroidUtilities.bold()); + giftRibbonText.ellipsize(dp(62)); + } else { + giftRibbonPath = null; + giftRibbonText = null; + } } private float measureLayoutWidth(Layout layout) { @@ -1516,6 +1844,7 @@ public int getCustomDate() { @Override protected void onDraw(Canvas canvas) { MessageObject messageObject = currentMessageObject; + final float expanded = giftPremiumTextExpandedAnimated.set(!giftPremiumTextCollapsed); int imageSize = stickerSize; if (isButtonLayout(messageObject)) { stickerSize = giftRectSize - dp(106); @@ -1534,9 +1863,16 @@ protected void onDraw(Canvas canvas) { } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL) { imageSize = (int) (stickerSize * (AndroidUtilities.isTablet() ? 1.0f : 1.2f)); imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - dp(22), imageSize, imageSize); + } else if (messageObject.isStarGiftAction()) { + imageSize = (int) (stickerSize * 1.1f); + imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - dp(0), imageSize, imageSize); } else if (messageObject.type == MessageObject.TYPE_GIFT_STARS) { imageSize = (int) (stickerSize * 1.1f); - imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - dp(22), imageSize, imageSize); + if (messageObject.messageOwner != null && !(messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift)) { + imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - dp(22), imageSize, imageSize); + } else { + imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - dp(12), imageSize, imageSize); + } } else { imageSize = (int) (stickerSize * 1f); imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - dp(4), imageSize, imageSize); @@ -1550,6 +1886,10 @@ protected void onDraw(Canvas canvas) { giftSubtitlePaint.setColor(textPaint.getColor()); giftSubtitlePaint.linkColor = textPaint.getColor(); } + if (giftTextPaint != null && giftTextPaint.getColor() != textPaint.getColor()) { + giftTextPaint.setColor(textPaint.getColor()); + giftTextPaint.linkColor = textPaint.getColor(); + } } } @@ -1646,12 +1986,11 @@ protected void onDraw(Canvas canvas) { if (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO) { y += dp(16); } - if (messageObject.type == MessageObject.TYPE_GIFT_STARS) { + if (messageObject.isStarGiftAction()) { + y += dp(12); + } else if (messageObject.type == MessageObject.TYPE_GIFT_STARS && !messageObject.isStarGiftAction()) { y -= dp(3.66f); } - if (giftPremiumButtonLayout == null) { - y -= dp(24); - } } canvas.translate(x, y); @@ -1661,6 +2000,13 @@ protected void onDraw(Canvas canvas) { giftPremiumTitleLayout.draw(canvas); canvas.restore(); y += giftPremiumTitleLayout.getHeight(); + if (giftPremiumSubtitleLayout != null) { + canvas.save(); + canvas.translate((giftRectSize - dp(16) - giftPremiumSubtitleLayout.getWidth()) / 2f, giftPremiumTitleLayout.getHeight() + dp(4)); + giftPremiumSubtitleLayout.draw(canvas); + canvas.restore(); + y += giftPremiumSubtitleLayout.getHeight() + dp(10); + } y += dp(messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL ? 6 : 0); } else { y -= dp(4); @@ -1668,6 +2014,9 @@ protected void onDraw(Canvas canvas) { canvas.restore(); y += dp(4); + if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { + y += dp(2); + } canvas.save(); canvas.translate(x, y); if (messageObject.type == MessageObject.TYPE_ACTION_WALLPAPER) { @@ -1689,31 +2038,37 @@ protected void onDraw(Canvas canvas) { loading.setSpan(loadingDots, 0, loading.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); cs.replace(index, index + len, loading); } - settingWallpaperLayout = new StaticLayout(cs, settingWallpaperPaint, giftPremiumSubtitleWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + settingWallpaperLayout = new StaticLayout(cs, settingWallpaperPaint, giftPremiumText == null ? 1 : giftPremiumText.width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } float progressLocal = getUploadingInfoProgress(messageObject); if (settingWallpaperProgressTextLayout == null || settingWallpaperProgress != progressLocal) { settingWallpaperProgress = progressLocal; - settingWallpaperProgressTextLayout = new StaticLayout((int) (progressLocal * 100) + "%", giftSubtitlePaint, giftPremiumSubtitleWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + settingWallpaperProgressTextLayout = new StaticLayout((int) (progressLocal * 100) + "%", giftTextPaint, giftPremiumText == null ? 1 : giftPremiumText.width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } - settingWallpaperPaint.setColor(giftSubtitlePaint.getColor()); + settingWallpaperPaint.setColor(giftTextPaint.getColor()); if (radialProgress.getIcon() == MediaActionDrawable.ICON_NONE) { float p = radialProgress.getTransitionProgress(); - int oldColor = giftSubtitlePaint.getColor(); + int oldColor = giftTextPaint.getColor(); settingWallpaperPaint.setAlpha((int) (Color.alpha(oldColor) * (1f - p))); - giftSubtitlePaint.setAlpha((int) (Color.alpha(oldColor) * p)); - giftSubtitlePaint.linkColor = giftSubtitlePaint.getColor(); - - float s = 0.8f + 0.2f * p; - canvas.save(); - canvas.scale(s, s, giftPremiumSubtitleWidth / 2f, giftPremiumSubtitleLayout.getHeight() / 2f); - canvas.translate((giftPremiumSubtitleWidth - giftPremiumSubtitleLayout.getWidth()) / 2f, 0); - SpoilerEffect.layoutDrawMaybe(giftPremiumSubtitleLayout, canvas); - canvas.restore(); + giftTextPaint.setAlpha((int) (Color.alpha(oldColor) * p)); + giftTextPaint.linkColor = giftTextPaint.getColor(); + + float s; + if (giftPremiumText != null) { + s = 0.8f + 0.2f * p; + canvas.save(); + canvas.scale(s, s, giftPremiumText.width / 2f, giftPremiumText.layout.getHeight() / 2f); + canvas.translate((giftPremiumText.width - giftPremiumText.layout.getWidth()) / 2f, 0); + giftPremiumText.x = x + (giftPremiumText.width - giftPremiumText.layout.getWidth()) / 2f; + giftPremiumText.y = y; + SpoilerEffect.renderWithRipple(this, false, giftTextPaint.getColor(), 0, giftPremiumText.patchedLayout, 1, giftPremiumText.layout, giftPremiumText.spoilers, canvas, false); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, giftPremiumText.layout, giftPremiumText.emoji, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(giftTextPaint.getColor())); + canvas.restore(); + } - giftSubtitlePaint.setAlpha((int) (Color.alpha(oldColor) * (1f - p))); - giftSubtitlePaint.linkColor = giftSubtitlePaint.getColor(); + giftTextPaint.setAlpha((int) (Color.alpha(oldColor) * (1f - p))); + giftTextPaint.linkColor = giftTextPaint.getColor(); s = 0.8f + 0.2f * (1f - p); canvas.save(); canvas.scale(s, s, settingWallpaperLayout.getWidth() / 2f, settingWallpaperLayout.getHeight() / 2f); @@ -1727,8 +2082,8 @@ protected void onDraw(Canvas canvas) { canvas.restore(); - giftSubtitlePaint.setColor(oldColor); - giftSubtitlePaint.linkColor = oldColor; + giftTextPaint.setColor(oldColor); + giftTextPaint.linkColor = oldColor; } else { settingWallpaperLayout.draw(canvas); canvas.save(); @@ -1736,17 +2091,52 @@ protected void onDraw(Canvas canvas) { SpoilerEffect.layoutDrawMaybe(settingWallpaperProgressTextLayout, canvas); canvas.restore(); } + } else if (giftPremiumText != null) { + canvas.save(); + canvas.translate((giftPremiumText.width - giftPremiumText.layout.getWidth()) / 2f, 0); + giftPremiumText.x = x + (giftPremiumText.width - giftPremiumText.layout.getWidth()) / 2f; + giftPremiumText.y = y; + SpoilerEffect.renderWithRipple(this, false, giftTextPaint.getColor(), 0, giftPremiumText.patchedLayout, 1, giftPremiumText.layout, giftPremiumText.spoilers, canvas, false); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, giftPremiumText.layout, giftPremiumText.emoji, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(giftTextPaint.getColor())); + canvas.restore(); + } + } else if (giftPremiumText != null) { + float h = giftPremiumText.layout.getHeight(); + if (expanded < 1) { + h = AndroidUtilities.lerp(giftPremiumTextCollapsedHeight, h, expanded); + AndroidUtilities.rectTmp.set(0, -dp(20), getWidth(), h); + canvas.saveLayerAlpha(AndroidUtilities.rectTmp, 0xFF, Canvas.ALL_SAVE_FLAG); } else { canvas.save(); - canvas.translate((giftPremiumSubtitleWidth - giftPremiumSubtitleLayout.getWidth()) / 2f, 0); - SpoilerEffect.layoutDrawMaybe(giftPremiumSubtitleLayout, canvas); + } + canvas.translate((giftRectSize - dp(16) - giftPremiumText.layout.getWidth()) / 2f, 0); + giftPremiumText.x = x + (giftRectSize - dp(16) - giftPremiumText.layout.getWidth()) / 2f; + giftPremiumText.y = y; + SpoilerEffect.renderWithRipple(this, false, giftPremiumText.paint.getColor(), 0, giftPremiumText.patchedLayout, 1, giftPremiumText.layout, giftPremiumText.spoilers, canvas, false); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, giftPremiumText.layout, giftPremiumText.emoji, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(giftTextPaint.getColor())); + if (expanded < 1 && giftPremiumTextMore != null) { + canvas.save(); + + if (giftPremiumTextClip == null) { + giftPremiumTextClip = new GradientClip(); + } + canvas.translate(-(giftRectSize - dp(16) - giftPremiumText.layout.getWidth()) / 2f, 0); + AndroidUtilities.rectTmp.set(giftPremiumTextMoreX - giftPremiumTextMore.getCurrentWidth() + dp(8), giftPremiumTextMoreY - giftPremiumTextMoreH - dp(6), giftPremiumTextMoreX + dp(6), giftPremiumTextMoreY); + giftPremiumTextClip.clipOut(canvas, AndroidUtilities.rectTmp, 1f - expanded); + AndroidUtilities.rectTmp.set(giftPremiumTextMoreX - giftPremiumTextMore.getCurrentWidth() - dp(16), giftPremiumTextMoreY - giftPremiumTextMoreH - dp(6), giftPremiumTextMoreX - giftPremiumTextMore.getCurrentWidth() + dp(8), giftPremiumTextMoreY); + giftPremiumTextClip.draw(canvas, AndroidUtilities.rectTmp, GradientClip.RIGHT, 1f - expanded); + + AndroidUtilities.rectTmp.set(0, h - dp(12), getWidth(), h); + float expX = 1f - expanded; + giftPremiumTextClip.draw(canvas, AndroidUtilities.rectTmp, GradientClip.BOTTOM, 4 * expX * (1 - expX)); + canvas.restore(); } - } else if (giftPremiumSubtitleLayout != null) { - canvas.save(); - canvas.translate((giftRectSize - dp(16) - giftPremiumSubtitleLayout.getWidth()) / 2f, 0); - SpoilerEffect.layoutDrawMaybe(giftPremiumSubtitleLayout, canvas); canvas.restore(); + + if (expanded < 1 && giftPremiumTextMore != null) { + giftPremiumTextMore.draw(canvas, giftPremiumTextMoreX - giftPremiumTextMore.getCurrentWidth() + dp(5), giftPremiumTextMoreY - giftPremiumTextMoreH / 2f - dp(1), giftPremiumText.paint.getColor(), 1f - expanded); + } } canvas.restore(); @@ -1754,7 +2144,9 @@ protected void onDraw(Canvas canvas) { y -= dp(8); } - y += giftPremiumSubtitleLayout.getHeight(); + if (giftPremiumText != null) { + y += AndroidUtilities.lerp(giftPremiumTextCollapsedHeight, giftPremiumText.layout.getHeight(), expanded); + } int buttonH = giftPremiumButtonLayout != null ? giftPremiumButtonLayout.getHeight() : 0; y += (getHeight() - y - buttonH - dp(8)) / 2f; @@ -1851,6 +2243,49 @@ protected void onDraw(Canvas canvas) { } canvas.restore(); + + if (backgroundRect != null && giftRibbonPath != null && giftRibbonText != null) { + final Paint backgroundPaint = getThemedPaint(Theme.key_paint_chatActionBackground); + final Paint darkenBackgroundPaint = getThemedPaint(Theme.key_paint_chatActionBackgroundDarken); + final float tx = backgroundRect.right - dp(65) + dp(2); + final float ty = backgroundRect.top - dp(2); + if (themeDelegate != null) { + themeDelegate.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, viewTranslationX + tx, viewTop + dp(4) + ty); + } else { + Theme.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, viewTranslationX + tx, viewTop + dp(4) + ty); + } + canvas.save(); + canvas.translate(tx, ty); + + ColorFilter wasColorFilter = backgroundPaint.getColorFilter(); + PathEffect wasPathEffect = backgroundPaint.getPathEffect(); + final boolean isDark = themeDelegate != null ? themeDelegate.isDark() : Theme.isCurrentThemeDark(); + if (giftRibbonPaintFilter == null || giftRibbonPaintFilterDark != isDark) { + ColorMatrix colorMatrix = new ColorMatrix(); + if (backgroundPaint.getColorFilter() instanceof ColorMatrixColorFilter && Build.VERSION.SDK_INT >= 26) { + ((ColorMatrixColorFilter) backgroundPaint.getColorFilter()).getColorMatrix(colorMatrix); + } + AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, isDark ? +.10f : -.08f); + AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, isDark ? +.15f : +.10f); + giftRibbonPaintFilter = new ColorMatrixColorFilter(colorMatrix); + giftRibbonPaintFilterDark = isDark; + } + backgroundPaint.setColorFilter(giftRibbonPaintFilter); + backgroundPaint.setPathEffect(giftRibbonPaintEffect); + canvas.drawPath(giftRibbonPath, backgroundPaint); + backgroundPaint.setColorFilter(wasColorFilter); + backgroundPaint.setPathEffect(wasPathEffect); + + if (hasGradientService()) { + wasPathEffect = darkenBackgroundPaint.getPathEffect(); + darkenBackgroundPaint.setPathEffect(giftRibbonPaintEffect); + canvas.drawPath(giftRibbonPath, darkenBackgroundPaint); + darkenBackgroundPaint.setPathEffect(wasPathEffect); + } + canvas.rotate(45, dp(40.43f), dp(24.56f)); + giftRibbonText.draw(canvas, dp(40.43f) - giftRibbonText.getCurrentWidth() / 2f, dp(26f), 0xFFFFFFFF, 1f); + canvas.restore(); + } } } @@ -2082,6 +2517,9 @@ public void drawBackground(Canvas canvas, boolean fromParent) { y += dp(12); AndroidUtilities.rectTmp.set(x, y, x + giftRectSize, y + giftRectSize + giftPremiumAdditionalHeight); } + if (messageObject != null && messageObject.type == MessageObject.TYPE_GIFT_PREMIUM && !giftPremiumTextCollapsed && giftPremiumText != null && giftPremiumTextCollapsedHeight > 0) { + AndroidUtilities.rectTmp.bottom -= (giftPremiumText.layout.getHeight() - giftPremiumTextCollapsedHeight) * (1f - giftPremiumTextExpandedAnimated.get()); + } if (backgroundRect == null) { backgroundRect = new RectF(); } 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 5bd5320662..84f5c45914 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -10,6 +10,7 @@ import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.dpf2; +import static org.telegram.messenger.AndroidUtilities.lerp; import static org.telegram.messenger.LocaleController.getString; import android.animation.Animator; @@ -186,6 +187,7 @@ import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.VectorAvatarThumbDrawable; import org.telegram.ui.Components.VideoForwardDrawable; +import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.Components.spoilers.SpoilerEffect2; import org.telegram.ui.GradientClip; @@ -734,12 +736,12 @@ default void forceUpdate(ChatMessageCell cell, boolean anchorScroll) { private final static int DOCUMENT_ATTACH_TYPE_STORY = 10; private class BotButton { - private int x; + private float x; private int y; - private int width; + private float width; private int height; private int positionFlags; - private StaticLayout title; + private Text title; private TLRPC.KeyboardButton button; private TLRPC.TL_reactionCount reaction; private int angle; @@ -2537,6 +2539,22 @@ private boolean checkLinkPreviewMotionEvent(MotionEvent event) { } else if (drawPhotoImage && currentMessageObject.sponsoredMedia != null && photoImage.isInsideImage(x, y) || drawPhotoImage && drawImageButton && buttonState != -1 && (!checkOnlyButtonPressed && photoImage.isInsideImage(x, y) || x >= buttonX && x <= buttonX + AndroidUtilities.dp(48) && y >= buttonY && y <= buttonY + AndroidUtilities.dp(48) && radialProgress.getIcon() != MediaActionDrawable.ICON_NONE)) { buttonPressed = 1; invalidate(); + if (currentMessageObject.sponsoredMedia != null && (MessageObject.isGifDocument(currentMessageObject.sponsoredMedia.document) || currentMessageObject.sponsoredMedia.photo != null)) { + if (Build.VERSION.SDK_INT >= 21) { + if (selectorDrawable[0] != null && selectorDrawable[0].getBounds().contains(x, y)) { + selectorDrawable[0].setHotspot(x, y); + selectorDrawable[0].setState(pressedState); + } + if (linkPreviewSelector != null && linkPreviewSelector.getBounds().contains(x, y)) { + linkPreviewSelector.setHotspot(x, y); + linkPreviewSelector.setState(pressedState); + } + setInstantButtonPressed(true); + } + if (linkPreviewBounce != null) { + linkPreviewBounce.setPressed(true); + } + } return true; } else { instantPressed = true; @@ -3788,6 +3806,7 @@ private boolean checkBotButtonMotionEvent(MotionEvent event) { boolean result = false; if (event.getAction() == MotionEvent.ACTION_DOWN) { + final int widthForButtons = getWidthForButtons(); int addX; if (currentMessageObject.isOutOwner()) { addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); @@ -3797,14 +3816,14 @@ private boolean checkBotButtonMotionEvent(MotionEvent event) { for (int a = 0; a < botButtons.size(); a++) { BotButton button = botButtons.get(a); int y2 = button.y + layoutHeight - AndroidUtilities.dp(2); - if (x >= button.x + addX && x <= button.x + addX + button.width && y >= y2 && y <= y2 + button.height) { + if (x >= button.x * widthForButtons + addX && x <= button.x * widthForButtons + addX + button.width * widthForButtons && y >= y2 && y <= y2 + button.height) { pressedBotButton = a; invalidateOutbounds(); result = true; if (button.selectorDrawable == null) { button.selectorDrawable = Theme.createRadSelectorDrawable(getThemedColor(Theme.key_chat_serviceBackgroundSelector), 6, 6); button.selectorDrawable.setCallback(this); - button.selectorDrawable.setBounds(button.x + addX, y2, button.x + addX + button.width, y2 + button.height); + button.selectorDrawable.setBounds((int) (button.x * widthForButtons) + addX, y2, (int) (button.x * widthForButtons) + addX + (int) (button.width * widthForButtons), y2 + button.height); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { button.selectorDrawable.setHotspot(x, y); @@ -5418,7 +5437,7 @@ private void fileAttach(boolean checkUI, final MessageObject messageObject) { if (messageObject != null && !messageObject.mediaExists) { int canDownload = DownloadController.getInstance(currentAccount).canDownloadMediaType(messageObject); TLRPC.Document document = messageObject.getDocument(); - boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document); + boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document) || messageObject.hasVideoQualities(); if (!loadDocumentFromImageReceiver && !isSmallImage) { TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()) : null; if (canDownload == 2 || canDownload == 1 && messageObject.isVideo()) { @@ -8877,7 +8896,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } else { w -= AndroidUtilities.dp(9); } - if (((isChat || m.isRepostPreview) && !isThreadPost && !m.isOutOwner() || m.forceAvatar) && m.needDrawAvatar() && (rowPosition == null || rowPosition.edge)) { + if (((isChat || m.isRepostPreview) && !isThreadPost && !m.isOutOwner() || m.forceAvatar || m.getDialogId() == UserObject.VERIFY) && m.needDrawAvatar() && (rowPosition == null || rowPosition.edge)) { w -= AndroidUtilities.dp(48); } w += getAdditionalWidthForPosition(rowPosition); @@ -9123,11 +9142,14 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe photoImage.setAllowStartAnimation(true); photoImage.startAnimation(); TLRPC.Document document = messageObject.getDocument(); + if (messageObject.hasVideoQualities()) { + document = VideoPlayer.getDocumentForThumb(currentAccount, MessageObject.getMedia(messageObject)); + } - if (currentMessageObject.videoEditedInfo != null && currentMessageObject.videoEditedInfo.canAutoPlaySourceVideo() && messageObject.getDocument() != null) { - photoImage.setImage(ImageLocation.getForPath(currentMessageObject.videoEditedInfo.originalPath), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, messageObject.getDocument().size, null, messageObject, 0); + if (currentMessageObject.videoEditedInfo != null && currentMessageObject.videoEditedInfo.canAutoPlaySourceVideo() && document != null) { + photoImage.setImage(ImageLocation.getForPath(currentMessageObject.videoEditedInfo.originalPath), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, document.size, null, messageObject, 0); photoImage.setMediaStartEndTime(currentMessageObject.videoEditedInfo.startTime / 1000, currentMessageObject.videoEditedInfo.endTime / 1000); - } else if (messageObject.getDocument() != null) { + } else if (document != null) { if (!messageIdChanged && !dataChanged) { photoImage.setCrossfadeWithOldImage(true); } @@ -9558,9 +9580,9 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } botButtonsByData.put(key, botButton); botButtonsByPosition.put(position, botButton); - botButton.x = column * (buttonWidth + AndroidUtilities.dp(5)); + botButton.x = (float) column * (buttonWidth + AndroidUtilities.dp(5)) / widthForButtons; botButton.y = row * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(2.5f); - botButton.width = buttonWidth; + botButton.width = (float) buttonWidth / widthForButtons; botButton.height = AndroidUtilities.dp(44); if (column == 0) { botButton.positionFlags |= MessageObject.POSITION_FLAG_LEFT; @@ -9584,12 +9606,21 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe if (botButton.button instanceof TLRPC.TL_keyboardButtonBuy && MessageObject.getMedia(messageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice) { buttonText = StarsIntroActivity.replaceStars(buttonText); } + if (botButton.button instanceof TLRPC.TL_keyboardButtonCopy) { + buttonText = new SpannableStringBuilder("c ").append(buttonText); + final ColoredImageSpan span = new ColoredImageSpan(R.drawable.menu_copy_s); + span.setScale(.9f, .9f); + ((SpannableStringBuilder) buttonText).setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } buttonText = Emoji.replaceEmoji(buttonText, botButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); - buttonText = TextUtils.ellipsize(buttonText, botButtonPaint, buttonWidth - AndroidUtilities.dp(10), TextUtils.TruncateAt.END); - botButton.title = new StaticLayout(buttonText, botButtonPaint, buttonWidth - AndroidUtilities.dp(10), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + if (oldButton != null && oldButton.title != null && TextUtils.equals(oldButton.title.getText(), buttonText)) { + botButton.title = oldButton.title; + } else { + botButton.title = new Text(buttonText, botButtonPaint); + } botButtons.add(botButton); if (column == buttonRow.buttons.size() - 1) { - maxButtonsWidth = Math.max(maxButtonsWidth, botButton.x + botButton.width); + maxButtonsWidth = Math.max(maxButtonsWidth, (int) (botButton.x * widthForButtons) + (int) (botButton.width * widthForButtons)); } if (messageObject.isFromUser() && botButton.button instanceof TLRPC.TL_keyboardButtonUrl) { try { @@ -11537,7 +11568,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto x = layoutWidth - backgroundWidth + AndroidUtilities.dp(6); } } else { - if ((isChat || currentMessageObject != null && currentMessageObject.forceAvatar) && isAvatarVisible && (!isPlayingRound || currentMessageObject.isVoiceTranscriptionOpen())) { + if ((isChat || currentMessageObject != null && currentMessageObject.forceAvatar || currentMessageObject.getDialogId() == UserObject.VERIFY) && isAvatarVisible && (!isPlayingRound || currentMessageObject.isVoiceTranscriptionOpen())) { x = AndroidUtilities.dp(63); } else { x = AndroidUtilities.dp(15); @@ -13954,6 +13985,7 @@ private void drawBotButtons(Canvas canvas, ArrayList botButtons, int if (SizeNotifierFrameLayout.drawingBlur) { return; } + final int widthForButtons = getWidthForButtons(); int addX; if (currentMessageObject != null && currentMessageObject.isOutOwner()) { addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); @@ -13981,7 +14013,7 @@ private void drawBotButtons(Canvas canvas, ArrayList botButtons, int float y = button.y + layoutHeight - AndroidUtilities.dp(2) + transitionParams.deltaBottom; float s = button.getPressScale(); - rect.set(button.x + addX, y, button.x + addX + button.width, y + button.height); + rect.set(button.x * widthForButtons + addX, y, button.x * widthForButtons + addX + button.width * widthForButtons, y + button.height); canvas.save(); if (s != 1) { canvas.scale(s, s, rect.centerX(), rect.centerY()); @@ -14039,19 +14071,19 @@ private void drawBotButtons(Canvas canvas, ArrayList botButtons, int } if (button.selectorDrawable != null) { - button.selectorDrawable.setBounds(button.x + addX, (int) y, button.x + addX + button.width, (int) y + button.height); + button.selectorDrawable.setBounds((int) (button.x * widthForButtons) + addX, (int) y, (int) (button.x * widthForButtons) + addX + (int) (button.width * widthForButtons), (int) y + button.height); button.selectorDrawable.setAlpha(0xFF); button.selectorDrawable.draw(canvas); } canvas.restore(); canvas.save(); - canvas.translate(button.x + addX + AndroidUtilities.dp(5), y + (AndroidUtilities.dp(44) - button.title.getLineBottom(button.title.getLineCount() - 1)) / 2); - button.title.draw(canvas); +// canvas.translate(button.x * widthForButtons + addX + AndroidUtilities.dp(5), y + (AndroidUtilities.dp(44) - button.title.getLineBottom(button.title.getLineCount() - 1)) / 2); + button.title.ellipsize(Math.max(1, (int) (button.width * widthForButtons) - dp(10))).draw(canvas, button.x * widthForButtons + addX + (button.width * widthForButtons - button.title.getWidth()) / 2f, y + dp(44) / 2f); canvas.restore(); if (button.button instanceof TLRPC.TL_keyboardButtonWebView) { Drawable drawable = getThemedDrawable(Theme.key_drawable_botWebView); - int x = button.x + button.width - AndroidUtilities.dp(3) - drawable.getIntrinsicWidth() + addX; + int x = (int) (button.x * widthForButtons) + (int) (button.width * widthForButtons) - AndroidUtilities.dp(3) - drawable.getIntrinsicWidth() + addX; setDrawableBounds(drawable, x, y + AndroidUtilities.dp(3)); drawable.draw(canvas); } else if (button.button instanceof TLRPC.TL_keyboardButtonUrl) { @@ -14063,16 +14095,16 @@ private void drawBotButtons(Canvas canvas, ArrayList botButtons, int } else { drawable = getThemedDrawable(Theme.key_drawable_botLink); } - int x = button.x + button.width - AndroidUtilities.dp(3) - drawable.getIntrinsicWidth() + addX; + int x = (int) (button.x * widthForButtons) + (int) (button.width * widthForButtons) - AndroidUtilities.dp(3) - drawable.getIntrinsicWidth() + addX; setDrawableBounds(drawable, x, y + AndroidUtilities.dp(3)); drawable.draw(canvas); } else if (button.button instanceof TLRPC.TL_keyboardButtonSwitchInline || button.button instanceof TLRPC.TL_keyboardButtonRequestPeer) { Drawable drawable = getThemedDrawable(Theme.key_drawable_botInline); - int x = button.x + button.width - AndroidUtilities.dp(3) - drawable.getIntrinsicWidth() + addX; + int x = (int) (button.x * widthForButtons) + (int) (button.width * widthForButtons) - AndroidUtilities.dp(3) - drawable.getIntrinsicWidth() + addX; setDrawableBounds(drawable, x, y + AndroidUtilities.dp(3)); drawable.draw(canvas); } else if (button.button instanceof TLRPC.TL_keyboardButtonBuy && hasInvoicePreview && hasInvoicePrice) { - int x = button.x + button.width - AndroidUtilities.dp(5) - Theme.chat_botCardDrawable.getIntrinsicWidth() + addX; + int x = (int) (button.x * widthForButtons) + (int) (button.width * widthForButtons) - AndroidUtilities.dp(5) - Theme.chat_botCardDrawable.getIntrinsicWidth() + addX; setDrawableBounds(Theme.chat_botCardDrawable, x, y + AndroidUtilities.dp(4)); Theme.chat_botCardDrawable.draw(canvas); } @@ -14513,7 +14545,7 @@ public void drawMessageText(float textX, float textY, Canvas canvas, ArrayList= 0) { + currentUser = messagesController.getUser(did); + } else { + currentChat = messagesController.getChat(-did); + } } else if (fwd_from != null && fwd_from.saved_from_peer != null) { if (fwd_from.saved_from_peer.user_id != 0) { if (!isSavedChat && fwd_from.from_id instanceof TLRPC.TL_peerUser) { @@ -16766,7 +16805,7 @@ protected void onClick() { } } replyTextRTL = AndroidUtilities.isRTL(sb); - if (isReplyQuote) { + if (isReplyQuote && !currentMessageObject.shouldDrawWithoutBackground()) { maxWidth += AndroidUtilities.dp(24 + 12); // replyTextWidth += AndroidUtilities.dp(24); } @@ -16874,7 +16913,7 @@ private String getNameFromDialogId(long fromId) { } protected boolean isNeedAuthorName() { - if (currentMessageObject.forceAvatar) { + if (currentMessageObject.forceAvatar || currentMessageObject.getDialogId() == UserObject.VERIFY && currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.fwd_from != null) { return true; } if (currentMessageObject.isSponsored()) { @@ -17106,6 +17145,7 @@ public int getBoundsLeft() { int buttonMostLeft = Integer.MAX_VALUE; if (botButtons != null) { int addX; + final int widthForButtons = getWidthForButtons(); if (currentMessageObject != null && currentMessageObject.isOutOwner()) { addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); } else { @@ -17113,7 +17153,7 @@ public int getBoundsLeft() { } for (int i = 0; i < botButtons.size(); ++i) { BotButton btn = botButtons.get(i); - buttonMostLeft = Math.max(buttonMostLeft, addX + btn.x); + buttonMostLeft = Math.max(buttonMostLeft, addX + (int) (btn.x * widthForButtons)); } } return Math.max(0, Math.min(buttonMostLeft, getBackgroundDrawableLeft() - avatarWidth - shareButtonWidth)); @@ -17126,14 +17166,15 @@ public int getBoundsRight() { int buttonMostRight = 0; if (botButtons != null) { int addX; + final int widthForButtons = getWidthForButtons(); if (currentMessageObject != null && currentMessageObject.isOutOwner()) { - addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + addX = getMeasuredWidth() - getWidthForButtons() - 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); + buttonMostRight = Math.max(buttonMostRight, addX + (int) (btn.x * widthForButtons) + (int) (btn.width * widthForButtons)); } } return Math.max(getBackgroundDrawableRight() + shareButtonWidth, buttonMostRight); @@ -17516,7 +17557,7 @@ public void drawBackgroundInternal(Canvas canvas, boolean fromParent) { currentBackgroundShadowDrawable = currentBackgroundDrawable.getShadowDrawable(); } - backgroundDrawableLeft = AndroidUtilities.dp(((isChat || currentMessageObject != null && (currentMessageObject.isRepostPreview || currentMessageObject.forceAvatar)) && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); + backgroundDrawableLeft = AndroidUtilities.dp(((isChat || currentMessageObject != null && (currentMessageObject.isRepostPreview || currentMessageObject.forceAvatar) || currentMessageObject.getDialogId() == UserObject.VERIFY) && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); backgroundDrawableRight = backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(3)); if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (!currentPosition.edge) { @@ -18095,7 +18136,11 @@ public void drawOutboundsContent(Canvas canvas) { drawBotButtons(canvas, transitionParams.transitionBotButtons, (int) (0xFF * t)); } if (!botButtons.isEmpty()) { - drawBotButtons(canvas, botButtons, transitionParams.animateBotButtonsChanged ? (int) (0xFF * transitionParams.animateChangeProgress) : 0xFF); + float alpha = 1f; + if (transitionParams.animateBotButtonsChanged) { + alpha = 1f - MathUtils.clamp(1f - (float) Math.pow(transitionParams.animateChangeProgress, 2f), 0f, 1f); + } + drawBotButtons(canvas, botButtons, (int) (alpha * 0xFF)); } drawSideButton(canvas); } @@ -18306,6 +18351,13 @@ private void drawSideButton(Canvas canvas) { sideStartY = sideMin; } } + if (currentMessageObject.type == MessageObject.TYPE_EMOJIS) { + if (drawSideButton == 3 && commentLayout != null) { + sideStartY = dp(18); + } else { + sideStartY = 0; + } + } if (!currentMessageObject.isOutOwner() && isRoundVideo && !hasLinkPreview) { float offsetSize = isAvatarVisible ? ((AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f) : AndroidUtilities.dp(50); float offsetX = isPlayingRound ? offsetSize * (1f - getVideoTranscriptionProgress()) : 0; @@ -18423,10 +18475,10 @@ public int getBackgroundDrawableLeft() { } else { int r; if (isRoundVideo) { - r = AndroidUtilities.dp(((isChat || messageObject != null && (messageObject.isRepostPreview || messageObject.forceAvatar)) && isAvatarVisible ? 48 : 0) + 3); + r = AndroidUtilities.dp(((isChat || messageObject != null && (messageObject.isRepostPreview || messageObject.forceAvatar) || messageObject.getDialogId() == UserObject.VERIFY) && isAvatarVisible ? 48 : 0) + 3); r += (int) (AndroidUtilities.dp(6) * (1f - getVideoTranscriptionProgress())); } else { - r = AndroidUtilities.dp(((isChat || messageObject != null && (messageObject.isRepostPreview || messageObject.forceAvatar)) && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); + r = AndroidUtilities.dp(((isChat || messageObject != null && (messageObject.isRepostPreview || messageObject.forceAvatar) || messageObject.getDialogId() == UserObject.VERIFY) && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); } if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (currentPosition.leftSpanOffset != 0) { @@ -18891,8 +18943,8 @@ public void drawNamesLayout(Canvas canvas, float alpha) { int backWidth = forwardedNameWidthLocal + AndroidUtilities.dp(14); if (hasReply) { needDrawReplyBackground = false; - int replyBackWidth = Math.max(replyNameWidth, replyTextWidth) - AndroidUtilities.dp(4); - rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), forwardNameRight = ((int) forwardNameXLocal - AndroidUtilities.dp(7) + Math.max(backWidth, replyBackWidth)), forwardNameY + forwardHeight + AndroidUtilities.dp(6) + AndroidUtilities.dp(41)); + int replyBackWidth = Math.max(replyNameWidth, replyTextWidth) - dp(4) + dp(7); + rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), forwardNameRight = ((int) forwardNameXLocal - AndroidUtilities.dp(7) + Math.max(backWidth, replyBackWidth)), forwardNameY + forwardHeight + dp(6) + replyHeight + dp(3)); } else { rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), (int) forwardNameXLocal - AndroidUtilities.dp(7) + backWidth, forwardNameY + forwardHeight + AndroidUtilities.dp(6)); } @@ -19393,7 +19445,7 @@ public void drawNamesLayout(Canvas canvas, float alpha) { final TextPaint paint = transitionParams.animateReplyTextLayout.getPaint(); int wasAlpha2 = paint.getAlpha(); paint.setAlpha((int) (wasAlpha2 * (1f - transitionParams.animateChangeProgress))); - SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, -AndroidUtilities.dp(2), spoilersPatchedReplyTextLayout, transitionParams.animateReplyTextLayout, replySpoilers, canvas, false); + SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, -AndroidUtilities.dp(2), spoilersPatchedReplyTextLayout, 0, transitionParams.animateReplyTextLayout, replySpoilers, canvas, false); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, transitionParams.animateReplyTextLayout, transitionParams.animateOutAnimateEmojiReply, 0, replySpoilers, 0, 0, 0, alpha, getAdaptiveEmojiColorFilter(2, paint.getColor())); paint.setAlpha(wasAlpha2); canvas.restore(); @@ -19414,7 +19466,7 @@ public void drawNamesLayout(Canvas canvas, float alpha) { final TextPaint paint = replyTextLayout.getPaint(); int wasAlpha2 = paint.getAlpha(); paint.setAlpha((int) (wasAlpha2 * (transitionParams.animateReplyTextLayout != null ? transitionParams.animateChangeProgress : 1))); - SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, -AndroidUtilities.dp(2), spoilersPatchedReplyTextLayout, replyTextLayout, replySpoilers, canvas, false); + SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, -AndroidUtilities.dp(2), spoilersPatchedReplyTextLayout, 0, replyTextLayout, replySpoilers, canvas, false); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, replyTextLayout, animatedEmojiReplyStack, 0, replySpoilers, 0, 0, 0, alpha, getAdaptiveEmojiColorFilter(2, paint.getColor())); paint.setAlpha(wasAlpha2); canvas.restore(); @@ -21324,9 +21376,10 @@ public void drawOverlays(Canvas canvas) { loadingProgressAlpha = animatingLoadingProgressProgress; } else { drawLoadingProgress = (buttonState == 1 || miniButtonState == 1 || animatingLoadingProgressProgress != 0) && !currentMessageObject.isSecretMedia() && - (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT); + (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) && + !currentMessageObject.hasVideoQualities(); if (currentMessageObject.type == MessageObject.TYPE_VIDEO || currentMessageObject.type == MessageObject.TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { - alpha = currentMessageObject.needDrawBluredPreview() && docTitleLayout == null ? 0 : animatingDrawVideoImageButtonProgress; + alpha = currentMessageObject.needDrawBluredPreview() && docTitleLayout == null || currentMessageObject.hasVideoQualities() ? 0 : animatingDrawVideoImageButtonProgress; } drawDocTitleLayout = alpha > 0 && docTitleLayout != null; if (!drawDocTitleLayout && (drawLoadingProgress || infoLayout == null)) { @@ -22077,7 +22130,7 @@ public void drawOverlays(Canvas canvas) { invalidate(); updateSecretTimeText(currentMessageObject); } - if ((drawVideoImageButton || animatingDrawVideoImageButton != 0) && !currentMessageObject.isRepostPreview && !currentMessageObject.sendPreview && photoImage.getVisible() && !isSmallImage && !currentMessageObject.isHiddenSensitive()) { + if ((drawVideoImageButton || animatingDrawVideoImageButton != 0) && !currentMessageObject.hasVideoQualities() && !currentMessageObject.isRepostPreview && !currentMessageObject.sendPreview && photoImage.getVisible() && !isSmallImage && !currentMessageObject.isHiddenSensitive()) { float alpha = controlsAlpha; if (drawPhotoImage && currentMessageObject != null && currentMessageObject.hasMediaSpoilers() && currentMessageObject.isSensitive() && (!currentMessageObject.isMediaSpoilersRevealed || mediaSpoilerRevealProgress != 0 && mediaSpoilerRevealProgress < 1)) { alpha *= mediaSpoilerRevealProgress; @@ -23291,10 +23344,10 @@ public void onClick(View view) { info.setClickable(true); info.addAction(AccessibilityNodeInfo.ACTION_CLICK); - rect.set(button.x, button.y, button.x + button.width, button.y + button.height); + rect.set((int) (button.x * widthForButtons), button.y, (int) ((button.x + button.width) * widthForButtons), button.y + button.height); int addX; if (currentMessageObject.isOutOwner()) { - addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + addX = getMeasuredWidth() - getWidthForButtons() - AndroidUtilities.dp(10); } else { addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground ? 1 : 7); } @@ -23908,6 +23961,9 @@ public class TransitionParams { public float animateChangeProgress = 1f; private ArrayList lastDrawBotButtons = new ArrayList<>(); private ArrayList transitionBotButtons = new ArrayList<>(); + public boolean animateWidthForButton; + public int animateFromWidthForButton; + public int lastDrawnWidthForButtons; public float lastButtonX; public float lastButtonY; @@ -24052,6 +24108,7 @@ public void recordDrawingState() { lastDrawingTextX = textX; lastDrawingLinkPreviewY = linkPreviewY; + lastDrawnWidthForButtons = widthForButtons; lastDrawnForwardedNameLayout[0] = forwardedNameLayout[0]; lastDrawnForwardedNameLayout[1] = forwardedNameLayout[1]; lastDrawnForwardedName = currentMessageObject != null && currentMessageObject.needDrawForwarded(); @@ -24264,7 +24321,7 @@ public boolean animateChange() { for (int i = 0; i < botButtons.size(); i++) { BotButton button1 = botButtons.get(i); BotButton button2 = lastDrawBotButtons.get(i); - if (button1.x != button2.x || button1.width != button2.width || button1.title != button2.title) { + if (Math.abs(button1.x - button2.x) > 0.01f || Math.abs(button1.width - button2.width) > 0.01f || !TextUtils.equals(button1.title.getText(), button2.title.getText())) { animateBotButtonsChanged = true; break; } @@ -24274,6 +24331,10 @@ public boolean animateChange() { transitionBotButtons.addAll(lastDrawBotButtons); } } + if (lastDrawnWidthForButtons != widthForButtons) { + animateFromWidthForButton = lastDrawnWidthForButtons; + animateWidthForButton = true; + } if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { if (buttonX != lastButtonX || buttonY != lastButtonY) { @@ -24482,6 +24543,8 @@ public void resetAnimation() { animateDrawingTimeAlpha = false; transitionBotButtons.clear(); animateButton = false; + animateBotButtonsChanged = false; + animateWidthForButton = false; animateMediaOffsetY = false; animateReplyTextLayout = null; @@ -24630,6 +24693,7 @@ public boolean needDrawAvatar() { isChat && !isSavedPreviewChat && (!isThreadPost || isForum) && ( currentMessageObject != null && !currentMessageObject.isOutOwner() && currentMessageObject.needDrawAvatar() ) || + currentMessageObject != null && currentMessageObject.getDialogId() == UserObject.VERIFY || currentMessageObject != null && currentMessageObject.forceAvatar ); } @@ -24767,4 +24831,11 @@ private int layoutFactCheck(final int maxTextWidth) { } return hasFactCheck ? factCheckHeight + addheight : 0; } + + public int getWidthForButtons() { + if (transitionParams.animateWidthForButton) { + return lerp(transitionParams.animateFromWidthForButton, widthForButtons, transitionParams.animateChangeProgress); + } + return widthForButtons; + } } 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 f0f081b117..1c2426e349 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -1488,7 +1488,12 @@ public void buildLayout() { if (!isSavedDialog && user != null && user.self && !message.isOutOwner()) { triedMessageName = AndroidUtilities.removeDiacritics(getMessageNameString()); } - if (isSavedDialog && user != null && !user.self && message != null && message.isOutOwner() || triedMessageName != null || chat != null && chat.id > 0 && (fromChat == null || fromChat.id != chat.id) && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat)) && !ForumUtilities.isTopicCreateMessage(message)) { + if ( + isSavedDialog && user != null && !user.self && message != null && message.isOutOwner() || + triedMessageName != null || + chat != null && chat.id > 0 && (fromChat == null || fromChat.id != chat.id) && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat)) && !ForumUtilities.isTopicCreateMessage(message) || + user != null && user.id == UserObject.VERIFY && message != null && message.getForwardedFromId() != null + ) { messageNameString = AndroidUtilities.removeDiacritics(triedMessageName != null ? triedMessageName : getMessageNameString()); if (chat != null && chat.forum && !isTopic && !useFromUserAsAvatar) { CharSequence topicName = MessagesController.getInstance(currentAccount).getTopicsController().getTopicIconName(chat, message, currentMessagePaint); @@ -5078,6 +5083,19 @@ public String getMessageNameString() { return AndroidUtilities.removeDiacritics(fromChat.title.replace("\n", "")); } return null; + } else if (currentDialogId == UserObject.VERIFY && message != null && message.messageOwner != null && message.messageOwner.fwd_from != null) { + if (message.messageOwner.fwd_from.from_name != null) { + return AndroidUtilities.removeDiacritics(message.messageOwner.fwd_from.from_name); + } else { + long did = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.from_id); + if (DialogObject.isUserDialog(did)) { + fromUser = MessagesController.getInstance(currentAccount).getUser(did); + return UserObject.getUserName(fromUser); + } else { + fromChat = MessagesController.getInstance(currentAccount).getChat(-did); + return fromChat == null ? "" : fromChat.title; + } + } } else if (message.isOutOwner() && fromUser != null) { return LocaleController.getString(R.string.FromYou); } else if (!isSavedDialog && message != null && message.messageOwner != null && message.messageOwner.from_id instanceof TLRPC.TL_peerUser && (user = MessagesController.getInstance(currentAccount).getUser(message.messageOwner.from_id.user_id)) != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditEmojiTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditEmojiTextCell.java new file mode 100644 index 0000000000..28c91c69cd --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditEmojiTextCell.java @@ -0,0 +1,287 @@ +package org.telegram.ui.Cells; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; +import static org.telegram.ui.Components.EditTextEmoji.STYLE_GIFT; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.Editable; +import android.text.InputType; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.TypedValue; +import android.view.ActionMode; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedColor; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.EditTextCaption; +import org.telegram.ui.Components.EditTextEmoji; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.SizeNotifierFrameLayout; +import org.telegram.ui.Components.TextStyleSpan; +import org.telegram.ui.Components.TypefaceSpan; + +public class EditEmojiTextCell extends FrameLayout { + + private boolean ignoreEditText; + public final EditTextEmoji editTextEmoji; + private int maxLength; + + private boolean showLimitWhenEmpty; + private int showLimitWhenNear = -1; + private boolean showLimitWhenFocused; + + public boolean autofocused; + private boolean focused; + + final AnimatedColor limitColor; + private int limitCount; + final AnimatedTextView.AnimatedTextDrawable limit = new AnimatedTextView.AnimatedTextDrawable(false, true, true); { + limit.setAnimationProperties(.2f, 0, 160, CubicBezierInterpolator.EASE_OUT_QUINT); + limit.setTextSize(dp(15.33f)); + limit.setGravity(Gravity.RIGHT); + } + + public void setShowLimitWhenEmpty(boolean show) { + showLimitWhenEmpty = show; + if (showLimitWhenEmpty) { + updateLimitText(); + } + } + + public void setShowLimitWhenNear(int near) { + showLimitWhenNear = near; + updateLimitText(); + } + + private void updateLimitText() { + if (editTextEmoji == null || editTextEmoji.getEditText() == null) return; + limitCount = maxLength - getText().length(); + limit.setText(TextUtils.isEmpty(getText()) && !showLimitWhenEmpty || showLimitWhenFocused && (!focused || autofocused) || (showLimitWhenNear != -1 && limitCount > showLimitWhenNear) ? "" : "" + limitCount); + } + + public void whenHitEnter(Runnable whenEnter) { + editTextEmoji.getEditText().setImeOptions(EditorInfo.IME_ACTION_DONE); + editTextEmoji.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + whenEnter.run(); + return true; + } + return false; + } + }); + } + + public void hideKeyboardOnEnter() { + whenHitEnter(() -> AndroidUtilities.hideKeyboard(editTextEmoji.getEditText())); + } + + + public void setShowLimitOnFocus(boolean show) { + showLimitWhenFocused = show; + } + + public EditEmojiTextCell(Context context, SizeNotifierFrameLayout parent, String hint, int style, boolean multiline) { + this(context, parent, hint, multiline, -1, style, null); + } + + public EditEmojiTextCell( + Context context, + SizeNotifierFrameLayout parent, + String hint, + boolean multiline, + int maxLength, + int style, + Theme.ResourcesProvider resourceProvider + ) { + super(context); + this.maxLength = maxLength; + + editTextEmoji = new EditTextEmoji(context, parent, null, style, true) { + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == limit || super.verifyDrawable(who); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + canvas.clipRect(getScrollX() + getPaddingLeft(), 0, getScrollX() + getWidth() - getPaddingRight(), getHeight()); + super.onDraw(canvas); + canvas.restore(); + + if (limitColor != null) { + limit.setTextColor(limitColor.set(Theme.getColor(limitCount <= 0 ? Theme.key_text_RedRegular : Theme.key_dialogSearchHint, resourceProvider))); + } + int h = Math.min(dp(48), getHeight()); + limit.setBounds(getScrollX(), getHeight() - h, getScrollX() + getWidth() - dp(12), getHeight()); + limit.draw(canvas); + } + + @Override + protected void extendActionMode(ActionMode actionMode, Menu menu) { + if (menu.findItem(R.id.menu_bold) != null) { + return; + } + if (Build.VERSION.SDK_INT >= 23) { + menu.removeItem(android.R.id.shareText); + } + int order = 6; + menu.add(R.id.menu_groupbolditalic, R.id.menu_spoiler, order++, LocaleController.getString(R.string.Spoiler)); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(getString(R.string.Bold)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, order++, stringBuilder); + stringBuilder = new SpannableStringBuilder(getString(R.string.Italic)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM_ITALIC)), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + menu.add(R.id.menu_groupbolditalic, R.id.menu_italic, order++, stringBuilder); +// menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, getString(R.string.CreateLink)); + stringBuilder = new SpannableStringBuilder(LocaleController.getString(R.string.Strike)); + TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; + stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + menu.add(R.id.menu_groupbolditalic, R.id.menu_strike, order++, stringBuilder); + menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, getString(R.string.Regular)); + } + }; + final EditTextCaption editText = editTextEmoji.getEditText(); + editText.setDelegate(new EditTextCaption.EditTextCaptionDelegate() { + @Override + public void onSpansChanged() { + onTextChanged(editText.getText()); + } + }); + editTextEmoji.setWillNotDraw(false); + limitColor = new AnimatedColor(editTextEmoji); + limit.setCallback(editTextEmoji); + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); + editText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText, resourceProvider)); + editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourceProvider)); + editText.setBackground(null); + if (multiline) { + editText.setMaxLines(5); + editText.setSingleLine(false); + } else { + editText.setMaxLines(1); + editText.setSingleLine(true); + } + editText.setPadding(editText.getPaddingLeft(), editText.getPaddingTop(), dp(style == STYLE_GIFT ? 0 : (maxLength > 0 ? 42 : 0) + 21), editText.getPaddingBottom()); + 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 | 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, resourceProvider)); + editText.setCursorSize(dp(19)); + editText.setCursorWidth(1.5f); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (!ignoreEditText) { + autofocused = false; + } + } + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {} + @Override + public void afterTextChanged(Editable editable) { + if (!ignoreEditText) { + if (maxLength > 0 && editable != null && editable.length() > maxLength) { + ignoreEditText = true; + editText.setText(editable.subSequence(0, maxLength)); + editText.setSelection(editText.length()); + ignoreEditText = false; + } + EditEmojiTextCell.this.onTextChanged(editable); + } + + if (multiline) { + int pos; + while ((pos = editable.toString().indexOf("\n")) >= 0) { + editable.delete(pos, pos + 1); + } + } + + if (limit != null && maxLength > 0) { + limit.cancelAnimation(); + updateLimitText(); + } + } + }); + editText.setOnFocusChangeListener(new OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + focused = hasFocus; + if (showLimitWhenFocused) { + updateLimitText(); + } + onFocusChanged(hasFocus); + } + }); + addView(editTextEmoji, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP)); + + updateLimitText(); + } + + public void setText(CharSequence text) { + ignoreEditText = true; + editTextEmoji.setText(text); + editTextEmoji.setSelection(editTextEmoji.getText().length()); + ignoreEditText = false; + } + + public CharSequence getText() { + return editTextEmoji.getText(); + } + + public boolean validate() { + return maxLength < 0 || editTextEmoji.getText().length() <= maxLength; + } + + protected void onTextChanged(CharSequence newText) { + + } + + protected void onFocusChanged(boolean focused) { + + } + + private boolean needDivider; + public void setDivider(boolean divider) { + setWillNotDraw(!(needDivider = divider)); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (needDivider) { + canvas.drawLine( + LocaleController.isRTL ? 0 : dp(22), + getMeasuredHeight() - 1, + getMeasuredWidth() - (LocaleController.isRTL ? dp(22) : 0), + getMeasuredHeight() - 1, + Theme.dividerPaint + ); + } + } +} \ No newline at end of file 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 e2ef26d325..16a6eb5de2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java @@ -1,20 +1,23 @@ package org.telegram.ui.Cells; -import static org.telegram.messenger.AndroidUtilities.decelerateInterpolator; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.Editable; -import android.text.InputFilter; import android.text.InputType; +import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.TextWatcher; import android.util.TypedValue; +import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; +import android.view.Menu; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; @@ -27,22 +30,22 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Business.QuickRepliesController; import org.telegram.ui.Components.AnimatedColor; import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CubicBezierInterpolator; -import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.EditTextCaption; import org.telegram.ui.Components.LayoutHelper; - -import java.util.ArrayList; +import org.telegram.ui.Components.TextStyleSpan; +import org.telegram.ui.Components.TypefaceSpan; public class EditTextCell extends FrameLayout { private boolean ignoreEditText; - public final EditTextBoldCursor editText; + public final EditTextCaption editText; private int maxLength; private boolean showLimitWhenEmpty; + private int showLimitWhenNear = -1; private boolean showLimitWhenFocused; public boolean autofocused; @@ -63,10 +66,15 @@ public void setShowLimitWhenEmpty(boolean show) { } } + public void setShowLimitWhenNear(int near) { + showLimitWhenNear = near; + updateLimitText(); + } + private void updateLimitText() { if (editText == null) return; limitCount = maxLength - getText().length(); - limit.setText(TextUtils.isEmpty(getText()) && !showLimitWhenEmpty || showLimitWhenFocused && (!focused || autofocused) ? "" : "" + limitCount); + limit.setText(TextUtils.isEmpty(getText()) && !showLimitWhenEmpty || showLimitWhenFocused && (!focused || autofocused) || (showLimitWhenNear != -1 && limitCount > showLimitWhenNear) ? "" : "" + limitCount); } public void whenHitEnter(Runnable whenEnter) { @@ -93,20 +101,20 @@ public void setShowLimitOnFocus(boolean show) { } public EditTextCell(Context context, String hint, boolean multiline) { - this(context, hint, multiline, -1, null); + this(context, hint, multiline, false, -1, null); } public EditTextCell( Context context, String hint, boolean multiline, - int maxLength, + boolean allowEntities, int maxLength, Theme.ResourcesProvider resourceProvider ) { super(context); this.maxLength = maxLength; - editText = new EditTextBoldCursor(context) { + editText = new EditTextCaption(context, resourceProvider) { @Override protected boolean verifyDrawable(@NonNull Drawable who) { return who == limit || super.verifyDrawable(who); @@ -136,6 +144,31 @@ protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.restore(); } + + @Override + protected void extendActionMode(ActionMode actionMode, Menu menu) { + if (!allowEntities) return; + if (menu.findItem(R.id.menu_bold) != null) { + return; + } + if (Build.VERSION.SDK_INT >= 23) { + menu.removeItem(android.R.id.shareText); + } + int order = 6; + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(getString(R.string.Bold)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, order++, stringBuilder); + stringBuilder = new SpannableStringBuilder(getString(R.string.Italic)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM_ITALIC)), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + menu.add(R.id.menu_groupbolditalic, R.id.menu_italic, order++, stringBuilder); +// menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, getString(R.string.CreateLink)); + stringBuilder = new SpannableStringBuilder(LocaleController.getString(R.string.Strike)); + TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; + stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + menu.add(R.id.menu_groupbolditalic, R.id.menu_strike, order++, stringBuilder); + menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, getString(R.string.Regular)); + } }; limit.setCallback(editText); editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); 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 9c1d493797..50356264b3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java @@ -74,7 +74,7 @@ public ProfileChannelCell(BaseFragment fragment) { 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.setBackgroundColor(0); dialogCell.setDialogCellDelegate(new DialogCell.DialogCellDelegate() { @Override public void onButtonClicked(DialogCell dialogCell) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index 1e553ff808..f4bca52566 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -495,6 +495,8 @@ public void buildLayout() { statusString = LocaleController.formatPluralStringSpaced("BotUsers", user.bot_active_users); } else if (user.bot) { statusString = LocaleController.getString(R.string.Bot); + } else if (user.id == UserObject.VERIFY) { + statusString = LocaleController.getString(R.string.VerifyCodesNotifications); } else if (UserObject.isService(user.id)) { statusString = LocaleController.getString(R.string.ServiceNotifications); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java index 1d62f114b6..500b599cb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java @@ -346,6 +346,10 @@ public static CombinedDrawable createDrawable(int sz, TLRPC.TL_authorization ses iconId = R.drawable.fragment; colorKey = -1; colorKey2 = -1; + } else if (platform.contains("anonymous")) { + iconId = R.drawable.large_hidden; + colorKey = Theme.key_avatar_backgroundBlue; + colorKey2 = Theme.key_avatar_background2Blue; } else if (platform.contains("premiumbot")) { iconId = R.drawable.filled_star_plus; colorKey = Theme.key_color_yellow; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index 3c68bd712a..21e91e70ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -801,7 +801,7 @@ protected void onDraw(Canvas canvas) { descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY); - SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout, descriptionLayout, descriptionLayoutSpoilers, canvas, false); + SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout, 0, descriptionLayout, descriptionLayoutSpoilers, canvas, false); canvas.restore(); } @@ -809,7 +809,7 @@ protected void onDraw(Canvas canvas) { descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), description2Y); - SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout2, descriptionLayout2, descriptionLayout2Spoilers, canvas, false); + SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout2, 0, descriptionLayout2, descriptionLayout2Spoilers, canvas, false); canvas.restore(); } 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 a0e23c117c..4471148764 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -570,7 +570,7 @@ public void update(int mask) { } nameTextView.setText(name); } - if (currentUser != null && MessagesController.getInstance(currentAccount).isPremiumUser(currentUser)) { + if (currentUser != null && MessagesController.getInstance(currentAccount).isPremiumUser(currentUser) && !MessagesController.getInstance(currentAccount).premiumFeaturesBlocked()) { if (currentUser.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) { emojiStatus.set(((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).document_id, false); emojiStatus.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 8a324a92c6..24975b3c1d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -2271,7 +2271,7 @@ private void processSelectedOption(int option) { getConnectionsManager().sendRequest(req, (res, err) -> { AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.TL_boolTrue) { - BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, getString("ChannelAntiSpamFalsePositiveReported", R.string.ChannelAntiSpamFalsePositiveReported)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, getString(R.string.ChannelAntiSpamFalsePositiveReported)).show(); } else if (res instanceof TLRPC.TL_boolFalse) { BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString("UnknownError", R.string.UnknownError)).show(); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java index 64e75b6b39..b2a35466d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java @@ -58,6 +58,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stats; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; @@ -1627,7 +1628,7 @@ public class ChannelTransactionsView extends LinearLayout { private final ArrayList tonTransactions = new ArrayList<>(); private int tonTransactionsTotalCount; - private final ArrayList starsTransactions = new ArrayList<>(); + private final ArrayList starsTransactions = new ArrayList<>(); private String starsLastOffset = ""; private class PageAdapter extends ViewPagerFixed.Adapter { @@ -1803,12 +1804,12 @@ private void loadTransactions(int type) { if (starsLastOffset == null || !starsRevenueAvailable) return; loadingTransactions[type] = true; - TLRPC.TL_payments_getStarsTransactions req = new TLRPC.TL_payments_getStarsTransactions(); + TL_stars.TL_payments_getStarsTransactions req = new TL_stars.TL_payments_getStarsTransactions(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); req.offset = starsLastOffset; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - if (res instanceof TLRPC.TL_payments_starsStatus) { - TLRPC.TL_payments_starsStatus r = (TLRPC.TL_payments_starsStatus) res; + if (res instanceof TL_stars.TL_payments_starsStatus) { + TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res; MessagesController.getInstance(currentAccount).putUsers(r.users, false); MessagesController.getInstance(currentAccount).putChats(r.chats, false); starsTransactions.addAll(r.history); @@ -1880,7 +1881,7 @@ protected void onAttachedToWindow() { private void fillItems(ArrayList items, UniversalAdapter adapter) { if (type == STARS_TRANSACTIONS) { - for (TLRPC.StarsTransaction t : starsTransactions) { + for (TL_stars.StarsTransaction t : starsTransactions) { items.add(StarsIntroActivity.StarsTransactionView.Factory.asTransaction(t, true)); } if (!TextUtils.isEmpty(starsLastOffset)) { @@ -1901,8 +1902,8 @@ private void fillItems(ArrayList items, UniversalAdapter adapter) { } private void onClick(UItem item, View view, int position, float x, float y) { - if (item.object instanceof TLRPC.StarsTransaction) { - StarsIntroActivity.showTransactionSheet(getContext(), true, dialogId, currentAccount, (TLRPC.StarsTransaction) item.object, resourcesProvider); + if (item.object instanceof TL_stars.StarsTransaction) { + StarsIntroActivity.showTransactionSheet(getContext(), true, dialogId, currentAccount, (TL_stars.StarsTransaction) item.object, resourcesProvider); } else if (item.object instanceof TL_stats.BroadcastRevenueTransaction) { showTransactionSheet(getContext(), currentAccount, (TL_stats.BroadcastRevenueTransaction) item.object, dialogId, resourcesProvider); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 0ffa5f9051..9584a7486f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -9,6 +9,7 @@ package org.telegram.ui; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.formatString; import static org.telegram.messenger.LocaleController.getString; import android.Manifest; @@ -75,6 +76,7 @@ import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.Pair; import android.util.Property; import android.util.SparseArray; @@ -222,7 +224,6 @@ import org.telegram.ui.Cells.ProfileChannelCell; import org.telegram.ui.Cells.ShareDialogCell; import org.telegram.ui.Cells.StickerCell; -import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.Components.*; import org.telegram.ui.Components.FloatingDebug.FloatingDebugController; @@ -264,6 +265,7 @@ import java.io.FileWriter; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.IDN; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; @@ -578,7 +580,11 @@ public ArrayList getFilteredMessages() { private int chatMode; private int scheduledMessagesCount = -1; - private int reportType = -1; + private String reportTitle; + private byte[] reportOption; + public boolean isReport() { + return !TextUtils.isEmpty(reportTitle); + } @Nullable private MessageObject threadMessageObject; @@ -590,7 +596,7 @@ public ArrayList getFilteredMessages() { private long threadMessageId; private int replyOriginalMessageId; private TLRPC.Chat replyOriginalChat; - private boolean isComments; + public boolean isComments; public boolean isTopic; private boolean threadMessageAdded; private boolean scrollToThreadMessage; @@ -1479,7 +1485,7 @@ public boolean onItemClick(View view, int position, float x, float y) { ChatActionCell actionCell = (ChatActionCell) view; showMenu = actionCell.getMessageObject().messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL || actionCell.getMessageObject().type == MessageObject.TYPE_SUGGEST_PHOTO || actionCell.getMessageObject().isWallpaperAction(); } - if (!actionBar.isActionModeShowed() && (reportType < 0 || showMenu)) { + if (!actionBar.isActionModeShowed() && (!isReport() || showMenu)) { result = createMenu(view, false, true, x, y, true); } else { boolean outside = false; @@ -1634,7 +1640,7 @@ public void onItemClick(View view, int position, float x, float y) { }, 16); return; } - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { boolean outside = false; if (view instanceof ChatMessageCell) { if (textSelectionHelper.isSelected(((ChatMessageCell) view).getMessageObject())) { @@ -1870,7 +1876,7 @@ public void onTextSelectionChanged(int start, int end) { editTextItem.setTag(1); if (editTextItem.getVisibility() != View.VISIBLE) { - if (chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && reportType < 0) { + if (chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && !isReport()) { editTextItem.setVisibility(View.VISIBLE); checkEditTextItemMenu(); if (headerItem != null) { @@ -1908,7 +1914,7 @@ public void onAnimationEnd(Animator animation) { if (editTextItem.getTag() != null) { editTextItem.setTag(null); if (editTextItem.getVisibility() != View.GONE) { - if (chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && reportType < 0) { + if (chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && !isReport()) { editTextItem.setVisibility(View.GONE); if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { @@ -2350,7 +2356,8 @@ public boolean onFragmentCreate() { if (startFromVideoTimestamp >= 0) { startFromVideoMessageId = startLoadFromMessageId; } - reportType = arguments.getInt("report", -1); + reportTitle = arguments.getString("reportTitle", null); + reportOption = arguments.getByteArray("reportOption"); pulled = arguments.getBoolean("pulled", false); historyPreloaded = arguments.getBoolean("historyPreloaded", false); if (highlightMessageId != 0 && highlightMessageId != Integer.MAX_VALUE) { @@ -3148,6 +3155,9 @@ protected Theme.ResourcesProvider getResourcesProvider() { @Override protected boolean canShowQuote() { + if (chatActivity != null && chatActivity.getDialogId() == UserObject.VERIFY) { + return false; + } final boolean noforwards = ( chatActivity != null && chatActivity.getMessagesController().isChatNoForwards(chatActivity.getCurrentChat()) || selectedView != null && selectedView.getMessageObject() != null && selectedView.getMessageObject().messageOwner != null && selectedView.getMessageObject().messageOwner.noforwards @@ -3167,6 +3177,9 @@ protected boolean canShowQuote() { @Override protected boolean canCopy() { + if (chatActivity != null && chatActivity.getDialogId() == UserObject.VERIFY) { + return true; + } return chatActivity == null || !( chatActivity.getDialogId() < 0 && chatActivity.getMessagesController().isChatNoForwards(-chatActivity.getDialogId()) || selectedView != null && selectedView.getMessageObject() != null && (selectedView.getMessageObject().messageOwner != null && selectedView.getMessageObject().messageOwner.noforwards) @@ -3235,7 +3248,7 @@ public View createView(Context context) { textSelectionHelper.setChatActivity(this); } - if (reportType >= 0) { + if (isReport()) { actionBar.setBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefault)); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); @@ -3311,7 +3324,7 @@ public View createView(Context context) { if (inPreviewMode) { actionBar.setBackButtonDrawable(null); } else { - actionBar.setBackButtonDrawable(new BackDrawable(reportType >= 0)); + actionBar.setBackButtonDrawable(new BackDrawable(isReport())); } actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -3480,7 +3493,7 @@ public void run(boolean revoke) { getNotificationCenter().postNotificationName(NotificationCenter.openBoostForUsersDialog, dialog_id); } } else if (id == report) { - AlertsCreator.createReportAlert(getParentActivity(), dialog_id, 0, 0, ChatActivity.this, themeDelegate, null); + ReportBottomSheet.openChat(ChatActivity.this); } else if (id == star) { for (int a = 0; a < 2; a++) { for (int b = 0; b < selectedMessagesCanStarIds[a].size(); b++) { @@ -3692,7 +3705,7 @@ protected boolean useAnimatedSubtitle() { @Override protected boolean canSearch() { - return !isInsideContainer && !isInPreviewMode() && !inBubbleMode && searchItem != null && !searching; + return !isInsideContainer && !isInPreviewMode() && !inBubbleMode && searchItem != null && !searching && (!isThreadChat() || isTopic); } @Override @@ -3709,20 +3722,8 @@ protected void openSearch() { if (inPreviewMode || inBubbleMode || isInsideContainer) { avatarContainer.setOccupyStatusBar(false); } - if (reportType >= 0) { - if (reportType == AlertsCreator.REPORT_TYPE_SPAM) { - actionBar.setTitle(getString(R.string.ReportChatSpam)); - } else if (reportType == AlertsCreator.REPORT_TYPE_VIOLENCE) { - actionBar.setTitle(getString(R.string.ReportChatViolence)); - } else if (reportType == AlertsCreator.REPORT_TYPE_CHILD_ABUSE) { - actionBar.setTitle(getString(R.string.ReportChatChild)); - } else if (reportType == AlertsCreator.REPORT_TYPE_PORNOGRAPHY) { - actionBar.setTitle(getString(R.string.ReportChatPornography)); - } else if (reportType == AlertsCreator.REPORT_TYPE_ILLEGAL_DRUGS) { - actionBar.setTitle(getString(R.string.ReportChatIllegalDrugs)); - } else if (reportType == AlertsCreator.REPORT_TYPE_PERSONAL_DETAILS) { - actionBar.setTitle(getString(R.string.ReportChatPersonalDetails)); - } + if (isReport()) { + actionBar.setTitle(reportTitle); actionBar.setSubtitle(getString(R.string.ReportSelectMessages)); } else if (startLoadFromDate != 0) { final int date = startLoadFromDate; @@ -3783,7 +3784,7 @@ protected void openSearch() { menu.addItem(edit_quick_reply, R.drawable.group_edit).setContentDescription(LocaleController.getString(R.string.Edit)); } - if (currentEncryptedChat == null && (chatMode == 0 || chatMode == MODE_SAVED) && reportType < 0) { + if (currentEncryptedChat == null && (chatMode == 0 || chatMode == MODE_SAVED) && !isReport()) { searchIconItem = menu.addItem(search, isSupportedTags() ? R.drawable.navbar_search_tag : R.drawable.ic_ab_search); searchIconItem.setContentDescription(LocaleController.getString(R.string.Search)); searchItem = menu.addItem(chat_menu_search, R.drawable.ic_ab_search, themeDelegate); @@ -3798,7 +3799,7 @@ protected void openSearch() { searchItemVisible = false; } - if (chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && reportType < 0) { + if (chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && !isReport()) { TLRPC.UserFull userFull = null; if (currentUser != null) { audioCallIconItem = menu.lazilyAddItem(call, R.drawable.ic_call, themeDelegate); @@ -3822,7 +3823,7 @@ protected void openSearch() { editTextItem.setTag(null); editTextItem.setVisibility(View.GONE); - if ((chatMode == 0 && (threadMessageId == 0 || isTopic)) && !UserObject.isReplyUser(currentUser) && reportType < 0) { + if ((chatMode == 0 && (threadMessageId == 0 || isTopic)) && !UserObject.isReplyUser(currentUser) && !isReport()) { TLRPC.UserFull userFull = null; if (currentUser != null) { userFull = getMessagesController().getUserFull(currentUser.id); @@ -3939,7 +3940,7 @@ public void toggleMute() { if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString(R.string.ReportChat)); } - if (currentUser != null) { + if (currentUser != null && currentUser.id != UserObject.VERIFY && currentUser.id != UserObject.REPLY_BOT) { addContactItem = headerItem.lazilyAddSubItem(share_contact, R.drawable.msg_addcontact, LocaleController.getString(R.string.AddToContacts)); } if (currentEncryptedChat != null) { @@ -3951,7 +3952,7 @@ public void toggleMute() { if (themeDelegate.isThemeChangeAvailable(true)) { headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_background, LocaleController.getString(R.string.SetWallpapers)); } - if (currentUser != null && currentUser.self) { + if (currentUser != null && currentUser.self && getDialogId() != UserObject.VERIFY) { headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString(R.string.AddShortcut)); } if (!isTopic) { @@ -3967,14 +3968,16 @@ public void toggleMute() { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveChannelMenu)); } } - } else if (!ChatObject.isChannel(currentChat)) { + } else if (!ChatObject.isChannel(currentChat) && getDialogId() != UserObject.VERIFY) { if (currentChat != null) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.DeleteAndExit)); } else if (currentUser != null && currentUser.bot) { headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString(R.string.BotSettings)); addedSettings = true; headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString(R.string.BotHelp)); - headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString(R.string.ReportBot)).setColors(getThemedColor(Theme.key_text_RedRegular), getThemedColor(Theme.key_text_RedRegular)); + if (!MessagesController.isSupportUser(currentUser)) { + headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString(R.string.ReportBot)).setColors(getThemedColor(Theme.key_text_RedRegular), getThemedColor(Theme.key_text_RedRegular)); + } headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_text_RedRegular), getThemedColor(Theme.key_text_RedRegular)); updateBotButtons(); } else { @@ -4016,7 +4019,7 @@ public void toggleMute() { avatarContainer.updateSubtitle(); updateTitleIcons(); - if (chatMode == 0 && (!isThreadChat() || isTopic) && reportType < 0) { + if (chatMode == 0 && (!isThreadChat() || isTopic) && !isReport()) { attachItem = menu.lazilyAddItem(chat_menu_attach, R.drawable.ic_ab_other, themeDelegate); attachItem.setOverrideMenuClick(true); attachItem.setAllowCloseAnimation(false); @@ -4226,7 +4229,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { return false; } boolean result = super.onInterceptTouchEvent(e); - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { return result; } processTouchEvent(e); @@ -4582,7 +4585,7 @@ public boolean onTouchEvent(MotionEvent e) { return false; } boolean result = super.onTouchEvent(e); - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { return result; } processTouchEvent(e); @@ -5882,9 +5885,36 @@ public void scrollToPositionWithOffset(int position, int offset, boolean bottom) if (!bottom) { offset = (int) (offset - getPaddingTop() + chatListViewPaddingTop); } + if (BuildVars.DEBUG_PRIVATE_VERSION) { + FileLog.e("scrollToPositionWithOffset " + position + " " + offset + " " + bottom, new Exception()); + } super.scrollToPositionWithOffset(position, offset, bottom); } + @Override + public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { + if (BuildVars.DEBUG_PRIVATE_VERSION) { + FileLog.e("scrollHorizontallyBy " + dx, new Exception()); + } + return super.scrollHorizontallyBy(dx, recycler, state); + } + + @Override + public void scrollToPosition(int position) { + if (BuildVars.DEBUG_PRIVATE_VERSION) { + FileLog.e("scrollToPosition " + position, new Exception()); + } + super.scrollToPosition(position); + } + + @Override + public void scrollToPositionWithOffset(int position, int offset) { + if (BuildVars.DEBUG_PRIVATE_VERSION) { + FileLog.e("scrollToPositionWithOffset " + position + " " + offset, new Exception()); + } + super.scrollToPositionWithOffset(position, offset); + } + @Override public boolean supportsPredictiveItemAnimations() { return true; @@ -5893,6 +5923,9 @@ public boolean supportsPredictiveItemAnimations() { @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { scrollByTouch = false; + if (BuildVars.DEBUG_PRIVATE_VERSION) { + FileLog.e("smoothScrollToPosition " + position, new Exception()); + } LinearSmoothScrollerCustom linearSmoothScroller = new LinearSmoothScrollerCustom(recyclerView.getContext(), LinearSmoothScrollerCustom.POSITION_MIDDLE); linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); @@ -5981,7 +6014,7 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi if (!foundTopView) { scrolled = super.scrollVerticallyBy(dy, recycler, state); } - 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 (dy > 0 && scrolled == 0 && (ChatObject.isChannel(currentChat) && !currentChat.megagroup || isTopic) && chatMode != MODE_SAVED && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && !isReport()) { if (pullingDownOffset == 0 && pullingDownDrawable != null) { if (nextChannels != null && !nextChannels.isEmpty()) { pullingDownDrawable.updateDialog(nextChannels.get(0)); @@ -6311,7 +6344,7 @@ public void setTranslationY(float translationY) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (getAlpha() == 0 || actionBar.isActionModeShowed() || reportType >= 0) { + if (getAlpha() == 0 || actionBar.isActionModeShowed() || isReport()) { return false; } return super.onInterceptTouchEvent(ev); @@ -6319,7 +6352,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { @Override public boolean onTouchEvent(MotionEvent event) { - if (getAlpha() == 0 || actionBar.isActionModeShowed() || reportType >= 0) { + if (getAlpha() == 0 || actionBar.isActionModeShowed() || isReport()) { return false; } return super.onTouchEvent(event); @@ -6348,7 +6381,7 @@ protected void onDraw(Canvas canvas) { floatingDateView.setInvalidateColors(true); contentView.addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 4, 0, 0)); floatingDateView.setOnClickListener(view -> { - if (floatingDateView.getAlpha() == 0 || actionBar.isActionModeShowed() || reportType >= 0) { + if (floatingDateView.getAlpha() == 0 || actionBar.isActionModeShowed() || isReport()) { return; } Calendar calendar = Calendar.getInstance(); @@ -7359,7 +7392,7 @@ public void openKeyboard() { @Override public void checkAnimation() { - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { if (messageEditTextAnimator != null) { messageEditTextAnimator.cancel(); } @@ -7923,7 +7956,7 @@ public void setVisibility(int visibility) { bottomOverlayStartButton.setOnClickListener(v -> bottomOverlayChatText.callOnClick()); bottomOverlayChat.addView(bottomOverlayStartButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 8, 8, 8, 8)); - if (currentUser != null && currentUser.bot && !UserObject.isReplyUser(currentUser) && !isInScheduleMode() && chatMode != MODE_PINNED && chatMode != MODE_SAVED) { + if (currentUser != null && currentUser.bot && currentUser.id != UserObject.VERIFY && !UserObject.isDeleted(currentUser) && !UserObject.isReplyUser(currentUser) && !isInScheduleMode() && chatMode != MODE_PINNED && chatMode != MODE_SAVED && !isReport()) { bottomOverlayStartButton.setVisibility(View.VISIBLE); bottomOverlayChat.setVisibility(View.VISIBLE); } @@ -7978,23 +8011,23 @@ protected float getTopOffset() { args.putLong("chat_id", -dialogId); } presentFragment(new ChatActivity(args)); - } else if (reportType >= 0) { - showDialog(new ReportAlert(getParentActivity(), reportType, getResourceProvider()) { - @Override - protected void onSend(int type, String message) { - ArrayList ids = new ArrayList<>(); - for (int b = 0; b < selectedMessagesIds[0].size(); b++) { - ids.add(selectedMessagesIds[0].keyAt(b)); - } - TLRPC.InputPeer peer = currentUser != null ? MessagesController.getInputPeer(currentUser) : MessagesController.getInputPeer(currentChat); - AlertsCreator.sendReport(peer, reportType, message, ids, 0); + } else if (isReport()) { + ArrayList ids = new ArrayList<>(); + for (int b = 0; b < selectedMessagesIds[0].size(); b++) { + ids.add(selectedMessagesIds[0].keyAt(b)); + } + showBottomOverlayProgress(true, true); + ReportBottomSheet.continueReport(this, reportOption, ids, status -> { + showBottomOverlayProgress(true, false); + if (status) { finishFragment(); - chatActivityDelegate.onReport(); } }); } else if (chatMode == MODE_PINNED) { finishFragment(); chatActivityDelegate.onUnpin(true, bottomOverlayChatText.getTag() == null); + } else if (currentUser != null && currentUser.id == UserObject.VERIFY) { + toggleMute(true); } else if (currentUser != null && userBlocked) { if (currentUser.bot) { String botUserLast = botUser; @@ -8987,6 +9020,9 @@ private void createBottomMessagesActionButtons() { forwardButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); forwardButton.setOnClickListener(v -> openForward(false)); bottomMessagesActionContainer.addView(forwardButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP)); + if (getDialogId() == UserObject.VERIFY) { + forwardButton.setVisibility(View.GONE); + } } private void checkInstantSearch() { @@ -9346,7 +9382,7 @@ private void createActionMode() { } actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString(R.string.AddToFavorites))); actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString(R.string.Copy))); - if (!isSavedMessages) { + if (!isSavedMessages && getDialogId() != UserObject.VERIFY) { actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString(R.string.Forward))); } actionModeViews.add(actionMode.addItemWithWidth(share, R.drawable.msg_shareout, AndroidUtilities.dp(54), LocaleController.getString(R.string.ShareFile))); @@ -10219,7 +10255,7 @@ private void animateToNextChat() { replacingChatActivity = true; presentFragment(chatActivity, true); } - } else { + } else if (pullingDownDrawable.getChatId() != 0) { addToPulledDialogsMyself(); addToPulledDialogs(pullingDownDrawable.nextChat, null, pullingDownDrawable.nextDialogId, pullingDownDrawable.dialogFolderId, pullingDownDrawable.dialogFilterId); Bundle bundle = new Bundle(); @@ -11918,10 +11954,6 @@ public boolean hasReportSpam() { return topChatPanelView != null && topChatPanelView.getTag() == null && reportSpamButton.getVisibility() != View.GONE; } - public boolean isReport() { - return reportType >= 0; - } - public void setChatInvite(TLRPC.ChatInvite invite) { chatInvite = invite; } @@ -17171,6 +17203,10 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { invalidateMessagesVisiblePart(); updateTextureViewPosition(false, false); + if (getParentActivity() instanceof LaunchActivity && !((LaunchActivity) getParentActivity()).drawerLayoutContainer.allowDrawContent) { + updateChatListViewTopPadding(); + } + notifyHeightChanged(); } @@ -17649,7 +17685,7 @@ private void addToSelectedMessages(MessageObject messageObject, boolean outside, } if (selectedMessagesIds[index].indexOfKey(messageObject.getId()) >= 0) { selectedMessagesIds[index].remove(messageObject.getId()); - if (reportType < 0) { + if (!isReport()) { if ((messageObject.type == MessageObject.TYPE_TEXT || messageObject.isAnimatedEmoji() || messageObject.caption != null) && !(messageObject.messageOwner != null && messageObject.messageOwner.noforwards)) { selectedMessagesCanCopyIds[index].remove(messageObject.getId()); } @@ -17686,7 +17722,7 @@ private void addToSelectedMessages(MessageObject messageObject, boolean outside, return; } selectedMessagesIds[index].put(messageObject.getId(), messageObject); - if (reportType < 0) { + if (!isReport()) { if ((messageObject.type == MessageObject.TYPE_TEXT || messageObject.isAnimatedEmoji() || messageObject.caption != null) && !(messageObject.messageOwner != null && messageObject.messageOwner.noforwards)) { selectedMessagesCanCopyIds[index].put(messageObject.getId(), messageObject); } @@ -17722,7 +17758,7 @@ private void addToSelectedMessages(MessageObject messageObject, boolean outside, forwardButtonAnimation.cancel(); forwardButtonAnimation = null; } - if (last && actionBar.isActionModeShowed() && reportType < 0) { + if (last && actionBar.isActionModeShowed() && !isReport()) { int selectedCount = selectedMessagesIds[0].size() + selectedMessagesIds[1].size(); if (selectedCount == 0) { hideActionMode(); @@ -18075,7 +18111,7 @@ private void processRowSelect(View view, boolean outside, float touchX, float to } private void updateActionModeTitle() { - if (reportType < 0) { + if (!isReport()) { if (!actionBar.isActionModeShowed()) { return; } @@ -18172,7 +18208,7 @@ public void updateTitle(boolean animated) { avatarContainer.setTitle(AndroidUtilities.removeDiacritics(UserObject.getUserName(currentUser)), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), currentUser.emoji_status, animated); } } else { - avatarContainer.setTitle(AndroidUtilities.removeDiacritics(UserObject.getUserName(currentUser)), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), currentUser.emoji_status, animated); + avatarContainer.setTitle(AndroidUtilities.removeDiacritics(UserObject.getUserName(currentUser)), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), !MessagesController.isSupportUser(currentUser) ? currentUser.emoji_status : null, animated); } } setParentActivityTitle(avatarContainer.getTitleTextView().getText()); @@ -18873,7 +18909,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else { chatListView.setEmptyView(emptyViewContainer); } - chatAdapter.notifyDataSetChanged(true); + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(true); + } } resumeDelayedFragmentAnimation(); @@ -19607,6 +19645,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (!postponedScroll) { chatAdapter.notifyItemRangeInserted(1, newRowsCount); + chatAdapter.updateRowsSafe(); if (scrollToMessageObject != null) { int scrollToIndex = messages.indexOf(scrollToMessageObject); if (scrollToIndex > 0) { @@ -19642,7 +19681,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { scrollToMessage = null; } else if (first || scrollToTopOnResume || forceScrollToTop) { forceScrollToTop = false; - if (!postponedScroll) { + if (!postponedScroll && chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } if (isTopic && startLoadFromMessageId == getTopicId() && messArr.size() > 0 && messages.size() > 0 && messArr.size() - 1 < messages.size()) { @@ -19854,7 +19893,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { checkScrollForLoad(false); if (postponedScroll && !fakePostponedScroll) { - chatAdapter.notifyDataSetChanged(true); + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(true); + } if (progressDialog != null) { progressDialog.dismiss(); showMessagesSearchListView(false); @@ -21169,7 +21210,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } }); - chatAdapter.notifyDataSetChanged(true); + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(true); + } }); } else if (id == NotificationCenter.updateAllMessages) { long dialogId = (long) args[0]; @@ -21183,7 +21226,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } }); - chatAdapter.notifyDataSetChanged(false); + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(false); + } }); } else if (id == NotificationCenter.didVerifyMessagesStickers) { ArrayList messages = (ArrayList) args[0]; @@ -21361,7 +21406,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { }); } else if (id == NotificationCenter.notificationsSettingsUpdated) { updateTitleIcons(); - if (ChatObject.isChannel(currentChat) || UserObject.isReplyUser(currentUser)) { + if (ChatObject.isChannel(currentChat) || UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.id == UserObject.VERIFY) { updateBottomOverlay(); } } else if (id == NotificationCenter.replyMessagesDidLoad) { @@ -22242,8 +22287,10 @@ public void didReceivedNotification(int id, int account, final Object... args) { for (int j = 0; j < group.messages.size(); j++) { group.messages.get(j).forceUpdate = true; } - chatAdapter.notifyDataSetChanged(true); - } else { + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(true); + } + } else if (chatAdapter != null) { chatAdapter.updateRowAtPosition(chatListView.getChildAdapterPosition(child)); } } else { @@ -22429,6 +22476,7 @@ public void showQuoteMessageUpdate() { } private int getScrollingOffsetForView(View v) { + FileLog.d("getScrollingOffsetForView view=" + v + " results in {"+(chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom())+"} chatHeight=" + chatListView.getMeasuredHeight() + " bottom=" + v.getBottom() + " paddingBottom=" + chatListView.getPaddingBottom()); return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); } @@ -22635,7 +22683,7 @@ private void loadSendAsPeers(boolean animatedUpdate) { private boolean sponsoredMessagesAdded; private Pattern sponsoredUrlPattern; private void addSponsoredMessages(boolean animated) { - if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium() && getMessagesController().isSponsoredDisabled()) { + if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium() && getMessagesController().isSponsoredDisabled() || isReport()) { return; } MessagesController.SponsoredMessagesInfo res = getMessagesController().getSponsoredMessages(dialog_id); @@ -22657,7 +22705,7 @@ private void addSponsoredMessages(boolean animated) { try { postId = matcher.groupCount() >= 2 ? Integer.parseInt(matcher.group(2)) : 0; } catch (Exception e2) { - FileLog.e(e2); + FileLog.e(e2, false); } TLObject obj = getMessagesController().getUserOrChat(username); long did; @@ -23687,7 +23735,7 @@ private void processNewMessages(ArrayList arr) { } } else { if (child != null) { - chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, getScrollingOffsetForView(child)); + chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, getScrollingOffsetForView(child)); } } if (newMentionsCount != 0 && mentiondownButtonCounter != null) { @@ -24680,7 +24728,7 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { BaseFragment fragment = parentLayout.getFragmentStack().get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getTopicId() == getTopicId() && chatActivity.getChatMode() == getChatMode() && chatActivity.threadMessageId == threadMessageId && chatActivity.reportType == reportType) { + if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getTopicId() == getTopicId() && chatActivity.getChatMode() == getChatMode() && chatActivity.threadMessageId == threadMessageId && chatActivity.isReport() == isReport()) { fragment.removeSelfFromStack(); break; } @@ -25037,7 +25085,7 @@ private void updateBottomOverlay() { bottomOverlayChatText.setText(LocaleController.getString(currentUser != null ? R.string.SavedOpenChat : (ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.SavedOpenChannel : R.string.SavedOpenGroup))); showBottomOverlayProgress(false, false); } - } else if (reportType >= 0) { + } else if (isReport()) { updateActionModeTitle(); } else if (chatMode == MODE_PINNED) { boolean allowPin; @@ -25058,6 +25106,15 @@ private void updateBottomOverlay() { bottomOverlayChatText.setText(LocaleController.getString(R.string.HidePinnedMessages)); } showBottomOverlayProgress(false, false); + } else if (currentUser != null && currentUser.id == UserObject.VERIFY) { + if (!getMessagesController().isDialogMuted(dialog_id, getTopicId())) { + bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelMute), false); + bottomOverlayChatText.setEnabled(true); + } else { + bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelUnmute), true); + bottomOverlayChatText.setEnabled(true); + } + showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); } else if (currentChat != null) { long requestedTime = MessagesController.getNotificationsSettings(currentAccount).getLong("dialog_join_requested_time_" + dialog_id, -1); boolean shouldApply = false; @@ -25145,7 +25202,7 @@ private void updateBottomOverlay() { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelUnmute), true); } showBottomOverlayProgress(false, true); - } else if (botUser != null && currentUser.bot) { + } else if (botUser != null && currentUser.bot && !UserObject.isDeleted(currentUser)) { // bottomOverlayStartButton.setText(LocaleController.getString(R.string.BotStart)); if (bottomOverlayStartButton != null) { bottomOverlayStartButton.setVisibility(View.VISIBLE); @@ -25164,7 +25221,7 @@ private void updateBottomOverlay() { } } - if (currentChat != null && currentChat.gigagroup && reportType < 0 && chatMode == 0) { + if (currentChat != null && currentChat.gigagroup && !isReport() && chatMode == 0) { bottomOverlayImage.setVisibility(View.VISIBLE); } else { bottomOverlayImage.setVisibility(View.INVISIBLE); @@ -25304,7 +25361,7 @@ public void onAnimationEnd(Animator animation) { if (isInsideContainer || forceNoBottom) { bottomOverlayChat.setVisibility(View.GONE); chatActivityEnterView.setVisibility(View.GONE); - } else if (reportType >= 0) { + } else if (isReport()) { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (chatMode == MODE_PINNED || @@ -25336,7 +25393,7 @@ public void onAnimationEnd(Animator animation) { headerItem.setVisibility(View.VISIBLE); } } else { - if (botUser != null && currentUser.bot || chatMode == MODE_SAVED && getSavedDialogId() != getUserConfig().getClientUserId()) { + if (botUser != null && currentUser.bot || currentUser != null && currentUser.id == UserObject.VERIFY || chatMode == MODE_SAVED && getSavedDialogId() != getUserConfig().getClientUserId()) { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else { @@ -25745,7 +25802,7 @@ private void updatePinnedMessageView(boolean animated, int animateToNext) { TLRPC.KeyboardButton botButton = pinnedButton(pinnedMessageObject); pinnedMessageButtonShown = botButton != null; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - if ((threadMessageObject == null || isTopic) && (chatInfo == null && userInfo == null || pinned_msg_id == 0 || !pinnedMessageIds.isEmpty() && pinnedMessageIds.get(0) == preferences.getInt("pin_" + dialog_id, 0)) || reportType >= 0 || actionBar != null && (actionBar.isActionModeShowed() || actionBar.isSearchFieldVisible())) { + if ((threadMessageObject == null || isTopic) && (chatInfo == null && userInfo == null || pinned_msg_id == 0 || !pinnedMessageIds.isEmpty() && pinnedMessageIds.get(0) == preferences.getInt("pin_" + dialog_id, 0)) || isReport() || actionBar != null && (actionBar.isActionModeShowed() || actionBar.isSearchFieldVisible())) { changed = hidePinnedMessageView(animated); } else { if (pinnedMessageView == null) { @@ -26451,7 +26508,7 @@ private void updateTopPanel(boolean animated) { boolean chatWithAdminChannel = preferences.getBoolean("dialog_bar_chat_with_channel" + did, false); int chatWithAdminDate = preferences.getInt("dialog_bar_chat_with_date" + did, 0); boolean showAddMembersToGroup = preferences.getBoolean("dialog_bar_invite" + did, false); - TLRPC.EmojiStatus showEmojiStatusReport = currentUser != null && (showReport || showBlock) && (currentUser.emoji_status instanceof TLRPC.TL_emojiStatus || currentUser.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) ? currentUser.emoji_status : null; + TLRPC.EmojiStatus showEmojiStatusReport = currentUser != null && (showReport || showBlock) && !getMessagesController().premiumFeaturesBlocked() && (currentUser.emoji_status instanceof TLRPC.TL_emojiStatus || currentUser.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) ? currentUser.emoji_status : null; boolean showRestartTopic = !isInPreviewMode() && forumTopic != null && forumTopic.closed && !forumTopic.hidden && ChatObject.canManageTopic(currentAccount, currentChat, forumTopic); boolean showTranslate = ( getUserConfig().isPremium() ? @@ -27153,7 +27210,7 @@ public float getPullingDownOffset() { public void checkAdjustResize() { if (isInsideContainer) return; - if (reportType >= 0) { + if (isReport()) { AndroidUtilities.requestAdjustNothing(getParentActivity(), classGuid); } else { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); @@ -27878,7 +27935,7 @@ private CharSequence getMessageCaption(MessageObject messageObject, MessageObjec @SuppressLint("ClickableViewAccessibility") private boolean createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup, boolean longpress) { - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { return false; } if (chatActivityEnterView != null) { @@ -28018,8 +28075,11 @@ private boolean createMenu(View v, boolean single, boolean listView, float x, fl } else { allowPin = false; } + if (UserObject.isReplyUser(dialog_id) || dialog_id == UserObject.VERIFY) { + allowPin = false; + } allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION; - boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards; + boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards || getDialogId() == UserObject.VERIFY; boolean noforwardsOrPaidMedia = noforwards || message.type == MessageObject.TYPE_PAID_MEDIA; boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())) && !message.isExpiredStory(); boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId && message.type != MessageObject.TYPE_STORY; @@ -29169,7 +29229,7 @@ public void run() { if (selectedObject == null) { return; } - logSponsoredClicked(selectedObject); + logSponsoredClicked(selectedObject, false, false); Browser.openUrl(getContext(), Uri.parse(selectedObject.sponsoredUrl), true, false, false, null, null, false, getMessagesController().sponsoredLinksInappAllow); }); textView.setOnLongClickListener(e -> { @@ -29549,7 +29609,7 @@ public void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, f } } - 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; + 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 && getDialogId() != UserObject.VERIFY; 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) { @@ -30441,26 +30501,20 @@ private void unpinMessage(MessageObject messageObject) { }, themeDelegate).show(); } - public void openReportChat(int type) { + public static ChatActivity openReportChat(long dialogId, String title, byte[] option) { + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return null; Bundle args = new Bundle(); - if (DialogObject.isUserDialog(dialog_id)) { - args.putLong("user_id", dialog_id); + if (DialogObject.isUserDialog(dialogId)) { + args.putLong("user_id", dialogId); } else { - args.putLong("chat_id", -dialog_id); + args.putLong("chat_id", -dialogId); } - args.putInt("report", type); - ChatActivity fragment = new ChatActivity(args); - presentFragment(fragment); - fragment.chatActivityDelegate = new ChatActivityDelegate() { - @Override - public void onReport() { - createUndoView(); - if (undoView == null) { - return; - } - undoView.showWithAction(0, UndoView.ACTION_REPORT_SENT, null); - } - }; + args.putString("reportTitle", title); + args.putByteArray("reportOption", option); + final ChatActivity fragment = new ChatActivity(args); + lastFragment.presentFragment(fragment); + return fragment; } private void saveMessageToGallery(MessageObject messageObject) { @@ -30474,6 +30528,11 @@ private void saveMessageToGallery(MessageObject messageObject) { if (TextUtils.isEmpty(path)) { path = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner).toString(); } + if (messageObject.qualityToSave != null) { + File f = FileLoader.getInstance(currentAccount).getPathToAttach(messageObject.qualityToSave, null, false, true); + if (f == null) return; + path = f.getPath(); + } MediaController.saveFile(path, getParentActivity(), messageObject.isVideo() ? 1 : 0, null, null); } @@ -30999,8 +31058,7 @@ private void processSelectedOption(int option) { AlertsCreator.showBlockReportSpamReplyAlert(ChatActivity.this, selectedObject, MessageObject.getPeerId(selectedObject.messageOwner.fwd_from.from_id), themeDelegate, () -> dimBehindView(false)); } } else { - preserveDim = true; - AlertsCreator.createReportAlert(getParentActivity(), dialog_id, selectedObject.getId(), 0, ChatActivity.this, themeDelegate, () -> dimBehindView(false)); + ReportBottomSheet.openMessage(ChatActivity.this, selectedObject); } break; } @@ -31169,99 +31227,7 @@ private void processSelectedOption(int option) { } case OPTION_REPORT_AD: { MessageObject message = selectedObject; - TLRPC.TL_channels_reportSponsoredMessage req = new TLRPC.TL_channels_reportSponsoredMessage(); - req.channel = MessagesController.getInputChannel(currentChat); - req.random_id = selectedObject.sponsoredId; - req.option = new byte[]{}; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (response != null) { - if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) { - AndroidUtilities.runOnUIThread(() -> { - TLRPC.TL_channels_sponsoredMessageReportResultChooseOption result = (TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) response; - new ReportAdBottomSheet(contentView.getContext(), resourceProvider, message, currentChat) - .setReportChooseOption(result) - .setListener(new ReportAdBottomSheet.Listener() { - @Override - public void onReported() { - AndroidUtilities.runOnUIThread(() -> { - BulletinFactory.of(ChatActivity.this) - .createAdReportedBulletin( - AndroidUtilities.replaceSingleTag( - LocaleController.getString(R.string.AdReported), - -1, - AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, - () -> Browser.openUrl(getContext(), "https://promote.telegram.org/guidelines"), - resourceProvider - ) - ) - .show(); - removeFromSponsored(message); - removeMessageWithThanos(message); - }, 200); - } - - @Override - public void onHidden() { - AndroidUtilities.runOnUIThread(() -> { - BulletinFactory.of(ChatActivity.this) - .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) - .show(); - removeFromSponsored(message); - removeMessageWithThanos(message); - }, 200); - } - - @Override - public void onPremiumRequired() { - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); - } - }) - .show(); - }); - } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultReported) { - AndroidUtilities.runOnUIThread(() -> { - BulletinFactory.of(ChatActivity.this) - .createAdReportedBulletin( - AndroidUtilities.replaceSingleTag( - LocaleController.getString(R.string.AdReported), - -1, - AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, - () -> Browser.openUrl(getContext(), "https://promote.telegram.org/guidelines"), - resourceProvider - ) - ) - .show(); - removeFromSponsored(message); - removeMessageWithThanos(message); - }, 200); - } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultAdsHidden) { - AndroidUtilities.runOnUIThread(() -> { - BulletinFactory.of(ChatActivity.this) - .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) - .show(); - getMessagesController().disableAds(false); - removeFromSponsored(message); - removeMessageWithThanos(message); - }, 200); - } - } else if (error != null && "AD_EXPIRED".equalsIgnoreCase(error.text)) { - AndroidUtilities.runOnUIThread(() -> { - BulletinFactory.of(ChatActivity.this) - .createAdReportedBulletin( - AndroidUtilities.replaceSingleTag( - LocaleController.getString(R.string.AdReported), - -1, - AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, - () -> Browser.openUrl(getContext(), "https://promote.telegram.org/guidelines"), - resourceProvider - ) - ) - .show(); - removeFromSponsored(message); - removeMessageWithThanos(message); - }, 200); - } - }); + ReportBottomSheet.openSponsored(ChatActivity.this, selectedObject, themeDelegate); break; } case OPTION_REMOVE_ADS: { @@ -31715,7 +31681,7 @@ private void updateVisibleRows(boolean suppressUpdateMessageObject) { boolean disableSelection = false; boolean selected = false; - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { highlightMessageQuoteFirst = false; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = null; @@ -32830,7 +32796,7 @@ private void openClickableLink(CharacterStyle url, String str, boolean longPress if (str.startsWith("video?")) { didPressMessageUrl(url, false, messageObject, cell); } else { - logSponsoredClicked(messageObject); + logSponsoredClicked(messageObject, false, false); openClickableLink(url, str, false, cell, messageObject, true); } } else if (which == 1) { @@ -32900,7 +32866,7 @@ private void openClickableLink(CharacterStyle url, String str, boolean longPress didLongPressLink(cell, messageObject, url, str); } } else { - logSponsoredClicked(messageObject); + logSponsoredClicked(messageObject, false, false); String username = Browser.extractUsername(str); if (username != null) { username = username.toLowerCase(); @@ -33087,13 +33053,15 @@ private void processExternalUrl(int type, String url, CharacterStyle span, ChatM } } - public void logSponsoredClicked(MessageObject messageObject) { + public void logSponsoredClicked(MessageObject messageObject, boolean media, boolean fullscreen) { if (messageObject == null || !messageObject.isSponsored()) { return; } TLRPC.TL_channels_clickSponsoredMessage req = new TLRPC.TL_channels_clickSponsoredMessage(); req.random_id = messageObject.sponsoredId; req.channel = getMessagesController().getInputChannel(-getDialogId()); + req.media = media; + req.fullscreen = fullscreen; getConnectionsManager().sendRequest(req, null); } @@ -33103,7 +33071,7 @@ private void didPressMessageUrl(CharacterStyle url, boolean longPress, MessageOb } boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.noforwards); if (url instanceof URLSpanMono) { - if (!noforwards) { + if (!noforwards || getDialogId() == UserObject.VERIFY) { ((URLSpanMono) url).copyToClipboard(); UndoView undoView = getUndoView(); if (undoView != null) { @@ -33121,7 +33089,7 @@ private void didPressMessageUrl(CharacterStyle url, boolean longPress, MessageOb if (longPress && cell != null) { cell.resetPressedLink(-1); } - logSponsoredClicked(messageObject); + logSponsoredClicked(messageObject, false, false); } else if (url instanceof URLSpanNoUnderline) { String str = ((URLSpanNoUnderline) url).getURL(); if (str != null && str.startsWith("tel:")) { @@ -33207,7 +33175,7 @@ private void didPressMessageUrl(CharacterStyle url, boolean longPress, MessageOb cell.resetPressedLink(-1); } } else { - logSponsoredClicked(messageObject); + logSponsoredClicked(messageObject, false, false); boolean forceAlert = url instanceof URLSpanReplacement; if (url instanceof URLSpanReplacement && (urlFinal == null || !urlFinal.startsWith("mailto:")) || AndroidUtilities.shouldShowUrlInAlert(urlFinal)) { if (openLinkInternally(urlFinal, cell, url, messageObject != null ? messageObject.getId() : 0)) { @@ -33526,6 +33494,39 @@ public void didOpenPremiumGift(ChatActionCell cell, TLRPC.TL_premiumGiftOption g } } + @Override + public void forceUpdate(ChatActionCell cell, boolean anchorScroll) { + if (cell == null) return; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject == null) return; + messageObject.forceUpdate = true; + int top = 0; + int position = RecyclerListView.NO_POSITION; + if (chatListView != null && chatLayoutManager != null && !chatLayoutManager.hasPendingScrollPosition()) { + for (int i = chatListView.getChildCount() - 1; i >= 0; i--) { + View v = chatListView.getChildAt(i); + final int vposition = chatListView.getChildAdapterPosition(v); + if (vposition < 0) continue; + if (v instanceof ChatMessageCell) { + if (((ChatMessageCell) v).getCurrentMessagesGroup() != null) { + continue; + } + position = vposition; + top = getScrollingOffsetForView(v); + break; + } else if (v instanceof ChatActionCell) { + position = vposition; + top = getScrollingOffsetForView(v); + break; + } + } + } + updateMessageAnimatedInternal(messageObject, false); + if (anchorScroll && position >= 0) { + chatLayoutManager.scrollToPositionWithOffset(position, top); + } + } + @Override public void didOpenPremiumGiftChannel(ChatActionCell cell, String slug, boolean animateConfetti) { initGiftProgressDialog(cell); @@ -33755,7 +33756,8 @@ public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && - !(button instanceof TLRPC.TL_keyboardButtonUserProfile) && !(button instanceof TLRPC.TL_keyboardButtonRequestPeer)) { + !(button instanceof TLRPC.TL_keyboardButtonUserProfile) && !(button instanceof TLRPC.TL_keyboardButtonRequestPeer) && + !(button instanceof TLRPC.TL_keyboardButtonCopy)) { return; } chatActivityEnterView.didPressedBotButton(button, messageObject, messageObject); @@ -33799,6 +33801,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { BotHelpCell helpView = (BotHelpCell) holder.itemView; if (UserObject.isReplyUser(currentUser)) { helpView.setText(false, LocaleController.getString(R.string.RepliesChatInfo)); + } else if (currentUser != null && currentUser.id == UserObject.VERIFY) { + helpView.setText(false, LocaleController.getString(R.string.VerifyChatInfo)); } else { TL_bots.BotInfo mBotInfo = botInfo.size() != 0 ? botInfo.get(currentUser.id) : null; helpView.setText(true, mBotInfo != null ? mBotInfo.description : null, mBotInfo != null ? mBotInfo.description_document != null ? mBotInfo.description_document : mBotInfo.description_photo : null, mBotInfo); @@ -34341,7 +34345,7 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { boolean selected = false; boolean disableSelection = false; - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { highlightMessageQuoteFirst = false; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = null; @@ -34620,7 +34624,7 @@ public void notifyItemMoved(int fromPosition, int toPosition) { @Override public void notifyItemRangeInserted(int positionStart, int itemCount) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("notify item range inserted" + positionStart + ":" + itemCount); + FileLog.d("notify item range inserted " + positionStart + ":" + itemCount); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); @@ -35396,7 +35400,7 @@ public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int pos if (chat == null) { return; } - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { processRowSelect(cell, true, touchX, touchY); return; } @@ -35505,7 +35509,7 @@ public void didPressUserStatus(ChatMessageCell cell, TLRPC.User user, TLRPC.Docu @Override public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY, boolean asForward) { - if (actionBar.isActionModeShowed() || reportType >= 0) { + if (actionBar.isActionModeShowed() || isReport()) { processRowSelect(cell, true, touchX, touchY); return; } @@ -35632,6 +35636,7 @@ private void openProfile(TLRPC.User user) { private void openProfile(TLRPC.User user, boolean expandPhoto) { if (user != null) { + if (user.id == UserObject.VERIFY) return; if (user.photo == null || user.photo instanceof TLRPC.TL_userProfilePhotoEmpty) { expandPhoto = false; } @@ -35718,7 +35723,8 @@ public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && - !(button instanceof TLRPC.TL_keyboardButtonUserProfile) && !(button instanceof TLRPC.TL_keyboardButtonRequestPeer)) { + !(button instanceof TLRPC.TL_keyboardButtonUserProfile) && !(button instanceof TLRPC.TL_keyboardButtonRequestPeer) && + !(button instanceof TLRPC.TL_keyboardButtonCopy)) { return; } chatActivityEnterView.didPressedBotButton(button, cell.getMessageObject(), cell.getMessageObject(), makeProgressForBotButton(cell, button instanceof TLRPC.TL_keyboardButtonUrl ? button.url : null)); @@ -35784,7 +35790,11 @@ public void didLongPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton but !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && - !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { + !(button instanceof TLRPC.TL_keyboardButtonUserProfile) && !(button instanceof TLRPC.TL_keyboardButtonCopy)) { + return; + } + if (button instanceof TLRPC.TL_keyboardButtonCopy) { + didLongPressCopyButton(((TLRPC.TL_keyboardButtonCopy) button).copy_text); return; } if (button instanceof TLRPC.TL_keyboardButtonUrl) { @@ -36171,7 +36181,7 @@ public void didLongPress(ChatMessageCell cell, float x, float y) { @Override public boolean canPerformActions() { - return actionBar != null && !actionBar.isActionModeShowed() && reportType < 0 && !inPreviewMode; + return actionBar != null && !actionBar.isActionModeShowed() && !isReport() && !inPreviewMode; } @Override @@ -36733,6 +36743,36 @@ public void didPressImage(ChatMessageCell cell, float x, float y) { alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } else if (message.isVideo() || message.type == MessageObject.TYPE_PHOTO || message.type == MessageObject.TYPE_TEXT && !message.isWebpageDocument() || message.isGif()) { + if (message.isSponsored()) { + if (message.isGif() || message.isPhoto()) { + logSponsoredClicked(message, true, false); + if (message.sponsoredUrl != null) { + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } + } + }; + Browser.openUrl(getContext(), Uri.parse(message.sponsoredUrl), true, false, false, progressDialogCurrent, null, false, getMessagesController().sponsoredLinksInappAllow); + } + return; + } else if (message.isVideo()) { + logSponsoredClicked(message, true, false); + } + } openPhotoViewerForMessage(cell, message); } else if (message.type == MessageObject.TYPE_VIDEO) { sendSecretMessageRead(message, true); @@ -36983,8 +37023,7 @@ public void end(boolean replaced) { Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, false, progressDialogCurrent, null, false, true); } else { if (messageObject.isSponsored()) { - logSponsoredClicked(messageObject); - Bundle args = new Bundle(); + logSponsoredClicked(messageObject, false, false); if (messageObject.sponsoredUrl != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); @@ -37618,7 +37657,7 @@ public ArrayList getThemeDescriptions() { themeDescriptions.add(new ThemeDescription(messagesSearchListContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); - if (reportType < 0) { + if (!isReport()) { themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); @@ -39283,7 +39322,7 @@ protected boolean hideKeyboardOnShow() { @Override public boolean isLightStatusBar() { - if (reportType >= 0) { + if (isReport()) { Theme.ResourcesProvider resourcesProvider = getResourceProvider(); int color; if (resourcesProvider != null) { @@ -39527,7 +39566,7 @@ public void didLongPressLink(ChatMessageCell cell, MessageObject messageObject, } else if (customTabs && !isHashtag) { Browser.openInTelegramBrowser(getParentActivity(), str, null); } else { - logSponsoredClicked(messageObject); + logSponsoredClicked(messageObject, false, false); openClickableLink(span, str, false, cell, messageObject, false); } }); @@ -39789,6 +39828,17 @@ public void didLongPressUsername(ChatMessageCell cell, CharacterStyle link, Stri } } + public void didLongPressCopyButton(String text) { + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, themeDelegate); + builder.setTitle(text); + builder.setTitleMultipleLines(true); + builder.setItems(new CharSequence[] { getString(R.string.Copy) }, (dialog, which) -> { + AndroidUtilities.addToClipboard(text); + BulletinFactory.of(ChatActivity.this).createCopyBulletin(formatString(R.string.ExactTextCopied, text)).show(); + }); + showDialog(builder.create()); + } + public void didPressPhoneNumber(ChatMessageCell cell, CharacterStyle link, String phone) { final Browser.Progress progress = makeProgressForLink(cell, link); final TLRPC.TL_contact contact = getContactsController().contactsByPhone.get(PhoneFormat.stripExceptNumbers(phone)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java index 4a58e65fdd..ae176d86da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java @@ -725,6 +725,7 @@ private TLRPC.TL_forumTopic getNextUnreadTopic(long currentDialogId) { } public long getChatId() { + if (nextChat == null) return 0; return nextChat.id; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index c332bdcfd6..968e60ed69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -1845,6 +1845,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int sentMediaCount = getSendMediaSelectedCount(); checkCell.setTextAndCheck(LocaleController.getString(R.string.UserRestrictionsSendMedia), sentMediaCount > 0, true, true); checkCell.setCollapseArrow(String.format(Locale.US, "%d/9", sentMediaCount), !sendMediaExpanded, () -> { + if (!checkCell.isEnabled()) return; if (allDefaultMediaBanned()) { new AlertDialog.Builder(getParentActivity()) .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) @@ -1863,6 +1864,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int count = getChannelMessagesSelectedCount(); checkCell.setTextAndCheck(LocaleController.getString(R.string.ChannelManageMessages), count > 0, true, true); checkCell.setCollapseArrow(String.format(Locale.US, "%d/3", count), !channelMessagesExpanded, () -> { + if (!checkCell.isEnabled()) return; boolean checked = checkCell.isChecked(); checkCell.setChecked(checked); setChannelMessagesEnabled(checked); @@ -1871,6 +1873,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int count = getChannelStoriesSelectedCount(); checkCell.setTextAndCheck(LocaleController.getString(R.string.ChannelManageStories), count > 0, true, true); checkCell.setCollapseArrow(String.format(Locale.US, "%d/3", count), !channelStoriesExpanded, () -> { + if (!checkCell.isEnabled()) return; boolean checked = checkCell.isChecked(); checkCell.setChecked(checked); setChannelStoriesEnabled(checked); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index aab3856ece..e3c3c8aab9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -692,8 +692,8 @@ protected void dispatchDraw(Canvas canvas) { progressBar.setVisibility(View.GONE); emptyView = new StickerEmptyView(context, progressLayout, StickerEmptyView.STICKER_TYPE_SEARCH); - emptyView.title.setText(getString("NoResult", R.string.NoResult)); - emptyView.subtitle.setText(getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2)); + emptyView.title.setText(getString(R.string.NoResult)); + emptyView.subtitle.setText(getString(R.string.SearchEmptyViewFilteredSubtitle2)); emptyView.setVisibility(View.GONE); emptyView.setAnimateLayoutChange(true); emptyView.showProgress(true, false); @@ -1101,7 +1101,9 @@ protected void onCancel() { } if (checkCell.hasIcon()) { if (ChatObject.isPublic(currentChat) && (position == pinMessagesRow || position == changeInfoRow)) { - BulletinFactory.of(this).createErrorBulletin(getString("EditCantEditPermissionsPublic", R.string.EditCantEditPermissionsPublic)).show(); + BulletinFactory.of(this).createErrorBulletin(getString(R.string.EditCantEditPermissionsPublic)).show(); + } else if (ChatObject.isDiscussionGroup(currentAccount, chatId) && (position == pinMessagesRow || position == changeInfoRow)) { + BulletinFactory.of(this).createErrorBulletin(getString(R.string.EditCantEditPermissionsDiscussion)).show(); } else { BulletinFactory.of(this).createErrorBulletin(getString("EditCantEditPermissions", R.string.EditCantEditPermissions)).show(); } @@ -3486,7 +3488,9 @@ public void run() { } else if (position == manageTopicsRow) { checkCell.setTextAndCheck(getString("CreateTopicsPermission", R.string.CreateTopicsPermission), !defaultBannedRights.manage_topics, false, animated); } - if (ChatObject.canBlockUsers(currentChat)) { + if ((position == pinMessagesRow || position == changeInfoRow) && ChatObject.isDiscussionGroup(currentAccount, chatId)) { + checkCell.setIcon(R.drawable.permission_locked); + } else if (ChatObject.canBlockUsers(currentChat)) { if (position == addUsersRow && !ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_INVITE) || position == pinMessagesRow && !ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_PIN) || position == changeInfoRow && !ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_CHANGE_INFO) || diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChooseDownloadQualityLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChooseDownloadQualityLayout.java new file mode 100644 index 0000000000..323ac976f6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChooseDownloadQualityLayout.java @@ -0,0 +1,100 @@ +package org.telegram.ui; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; + +import android.content.Context; +import android.text.TextUtils; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.PopupSwipeBackLayout; +import org.telegram.ui.Components.VideoPlayer; + +import java.util.ArrayList; + +public class ChooseDownloadQualityLayout { + + public final ActionBarPopupWindow.ActionBarPopupWindowLayout layout; + public final LinearLayout buttonsLayout; + private final Callback callback; + + public ChooseDownloadQualityLayout(Context context, PopupSwipeBackLayout swipeBackLayout, Callback callback) { + this.callback = callback; + layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, 0, null); + layout.setFitItems(true); + + ActionBarMenuSubItem backItem = ActionBarMenuItem.addItem(layout, R.drawable.msg_arrow_back, getString(R.string.Back), false, null); + backItem.setOnClickListener(view -> { + swipeBackLayout.closeForeground(); + }); + backItem.setColors(0xfffafafa, 0xfffafafa); + backItem.setSelectorColor(0x0fffffff); + + FrameLayout gap = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }; + gap.setMinimumWidth(dp(196)); + gap.setBackgroundColor(0xff181818); + layout.addView(gap); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) gap.getLayoutParams(); + if (LocaleController.isRTL) { + layoutParams.gravity = Gravity.RIGHT; + } + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.height = dp(8); + gap.setLayoutParams(layoutParams); + + buttonsLayout = new LinearLayout(context); + buttonsLayout.setOrientation(LinearLayout.VERTICAL); + layout.addView(buttonsLayout); + } + + public boolean update(MessageObject messageObject) { + if (messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.media == null) return false; + if (!messageObject.hasVideoQualities()) return false; + + ArrayList qualities = VideoPlayer.getQualities(messageObject.currentAccount, messageObject.messageOwner.media.document, messageObject.messageOwner.media.alt_documents, 0, false); + + buttonsLayout.removeAllViews(); + for (int i = 0; i < qualities.size(); ++i) { + final VideoPlayer.Quality q = qualities.get(i); + String title = "", subtitle = ""; + String str = q.toString(); + if (str.contains("\n")) { + title = str.substring(0, str.indexOf("\n")); + subtitle = str.substring(str.indexOf("\n") + 1); + } else { + title = str; + } + ActionBarMenuSubItem item = ActionBarMenuItem.addItem(buttonsLayout, 0, title, false, null); + if (!TextUtils.isEmpty(subtitle)) { + item.setSubtext(subtitle); + } + item.setColors(0xfffafafa, 0xfffafafa); + item.setOnClickListener((view) -> { + callback.onQualitySelected(messageObject, q); + }); + item.setSelectorColor(0x0fffffff); + } + return true; + } + + public interface Callback { + void onQualitySelected(MessageObject messageObject, VideoPlayer.Quality quality); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChooseQualityLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChooseQualityLayout.java new file mode 100644 index 0000000000..41f82c4e63 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChooseQualityLayout.java @@ -0,0 +1,196 @@ +package org.telegram.ui; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.PopupSwipeBackLayout; +import org.telegram.ui.Components.VideoPlayer; + +public class ChooseQualityLayout { + + public final ActionBarPopupWindow.ActionBarPopupWindowLayout layout; + public final LinearLayout buttonsLayout; + private final Callback callback; + + public ChooseQualityLayout(Context context, PopupSwipeBackLayout swipeBackLayout, Callback callback) { + this.callback = callback; + layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, 0, null); + layout.setFitItems(true); + + ActionBarMenuSubItem backItem = ActionBarMenuItem.addItem(layout, R.drawable.msg_arrow_back, getString(R.string.Back), false, null); + backItem.setOnClickListener(view -> { + swipeBackLayout.closeForeground(); + }); + backItem.setColors(0xfffafafa, 0xfffafafa); + backItem.setSelectorColor(0x0fffffff); + + FrameLayout gap = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }; + gap.setMinimumWidth(dp(196)); + gap.setBackgroundColor(0xff181818); + layout.addView(gap); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) gap.getLayoutParams(); + if (LocaleController.isRTL) { + layoutParams.gravity = Gravity.RIGHT; + } + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.height = dp(8); + gap.setLayoutParams(layoutParams); + + buttonsLayout = new LinearLayout(context); + buttonsLayout.setOrientation(LinearLayout.VERTICAL); + layout.addView(buttonsLayout); + } + + public boolean update(VideoPlayer player) { + if (player == null) return false; + if (player.getQualitiesCount() <= 1) return false; + + buttonsLayout.removeAllViews(); + for (int i = -1; i < player.getQualitiesCount(); ++i) { + final VideoPlayer.Quality q = i == -1 ? null : player.getQuality(i); + final int index = i; + String title = "", subtitle = ""; + if (q == null) { + title = getString(R.string.QualityAuto); + } else { + String str = q.toString(); + if (str.contains("\n")) { + title = str.substring(0, str.indexOf("\n")); + subtitle = str.substring(str.indexOf("\n") + 1); + } else { + title = str; + } + } + ActionBarMenuSubItem item = ActionBarMenuItem.addItem(buttonsLayout, 0, title, true, null); + if (!TextUtils.isEmpty(subtitle)) { + item.setSubtext(subtitle); + } + item.setChecked(index == player.getSelectedQuality()); + item.setColors(0xfffafafa, 0xfffafafa); + item.setOnClickListener((view) -> { + callback.onQualitySelected(index, true, true); + }); + item.setSelectorColor(0x0fffffff); + } + return true; + } + + public interface Callback { + void onQualitySelected(int qualityIndex, boolean isFinal, boolean closeMenu); + } + + public static class QualityIcon extends Drawable { + + private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Drawable base; + private final RectF rect = new RectF(); + public final AnimatedTextView.AnimatedTextDrawable text = new AnimatedTextView.AnimatedTextDrawable(); + + public QualityIcon(Context context) { + base = context.getResources().getDrawable(R.drawable.msg_settings).mutate(); + + text.setTypeface(AndroidUtilities.getTypeface("fonts/num.otf")); + text.setTextColor(0xFFFFFFFF); + text.setTextSize(dp(8)); + text.setCallback(new Callback() { + @Override + public void invalidateDrawable(@NonNull Drawable who) { + QualityIcon.this.invalidateSelf(); + } + @Override + public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { + QualityIcon.this.scheduleSelf(what, when); + } + @Override + public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { + QualityIcon.this.unscheduleSelf(what); + } + }); + text.setGravity(Gravity.CENTER); + text.setOverrideFullWidth(AndroidUtilities.displaySize.x); + } + + private float rotation; + public void setRotation(float rotation) { + this.rotation = rotation; + invalidateSelf(); + } + + @Override + public void draw(@NonNull Canvas canvas) { + final Rect bounds = getBounds(); + + base.setBounds(bounds); + canvas.save(); + canvas.rotate(rotation * -180, bounds.centerX(), bounds.centerY()); + base.draw(canvas); + canvas.restore(); + + bgPaint.setColor(Theme.getColor(Theme.key_featuredStickers_addButton)); + final float right = bounds.left + bounds.width() * .97f; + final float cy = bounds.top + bounds.height() * .75f; + final float h = dp(11); + final float w = dp(5) * text.isNotEmpty() + text.getCurrentWidth(); + rect.set(right - w, cy - h / 2f, right, cy + h / 2f); + canvas.drawRoundRect(rect, dp(3), dp(3), bgPaint); + text.setBounds(rect); + text.draw(canvas); + } + + @Override + public void setAlpha(int alpha) { + base.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + base.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return base.getOpacity(); + } + + @Override + public int getIntrinsicWidth() { + return base.getIntrinsicWidth(); + } + + @Override + public int getIntrinsicHeight() { + return base.getIntrinsicHeight(); + } + } + +} 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 23a140ec51..d89d5c009c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -101,6 +101,7 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Business.TimezonesController; import org.telegram.ui.CacheControlActivity; @@ -117,6 +118,7 @@ import org.telegram.ui.NotificationsCustomSettingsActivity; import org.telegram.ui.NotificationsSettingsActivity; import org.telegram.ui.PrivacyControlActivity; +import org.telegram.ui.ProfileActivity; import org.telegram.ui.ProfileNotificationsActivity; import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.ThemePreviewActivity; @@ -274,6 +276,9 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base } else { peer = null; } + if (fragment == null) { + fragment = LaunchActivity.getLastFragment(); + } if (error.text.contains("USER_IS_BLOCKED")) { showSimpleAlert(fragment, LocaleController.getString(R.string.ImportErrorTitle), LocaleController.getString(R.string.ImportErrorUserBlocked)); } else if (error.text.contains("USER_NOT_MUTUAL_CONTACT")) { @@ -300,6 +305,9 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base showSimpleAlert(fragment, LocaleController.getString(R.string.ImportErrorTitle), LocaleController.getString(R.string.ErrorOccurred) + "\n" + error.text); } } else if (request instanceof TLRPC.TL_account_saveSecureValue || request instanceof TLRPC.TL_account_getAuthorizationForm) { + if (fragment == null) { + fragment = LaunchActivity.getLastFragment(); + } if (error.text.contains("PHONE_NUMBER_INVALID")) { showSimpleAlert(fragment, LocaleController.getString(R.string.InvalidPhoneNumber)); } else if (error.text.startsWith("FLOOD_WAIT")) { @@ -338,6 +346,9 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base } } } else if (request instanceof TLRPC.TL_messages_createChat) { + if (fragment == null) { + fragment = LaunchActivity.getLastFragment(); + } if (error.text.equals("CHANNELS_TOO_MUCH")) { if (fragment.getParentActivity() != null) { fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), LimitReachedBottomSheet.TYPE_TO0_MANY_COMMUNITIES, currentAccount, null)); @@ -351,6 +362,9 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base showAddUserAlert(error.text, fragment, false, request); } } else if (request instanceof TLRPC.TL_channels_createChannel) { + if (fragment == null) { + fragment = LaunchActivity.getLastFragment(); + } if (error.text.equals("CHANNELS_TOO_MUCH")) { if (fragment.getParentActivity() != null) { fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), LimitReachedBottomSheet.TYPE_TO0_MANY_COMMUNITIES, currentAccount, null)); @@ -442,6 +456,9 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base } } } else if (request instanceof TLRPC.TL_messages_importChatInvite) { + if (fragment == null) { + fragment = LaunchActivity.getLastFragment(); + } if (error.text.startsWith("FLOOD_WAIT")) { showSimpleAlert(fragment, LocaleController.getString(R.string.FloodWait)); } else if (error.text.equals("USERS_TOO_MUCH")) { @@ -1467,17 +1484,48 @@ public void setText(CharSequence text, BufferType type) { imageView.setRoundRadius(dp(20)); frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 22, 5, 22, 0)); - TextView textView = new TextView(context); + SimpleTextView textView = new SimpleTextView(context); textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setTextSize(20); textView.setTypeface(AndroidUtilities.bold()); - textView.setLines(1); - textView.setMaxLines(1); - textView.setSingleLine(true); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setEllipsizeByGradient(true); textView.setText(user.first_name); - frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 11, (LocaleController.isRTL ? 76 : 21), 0)); + if (user.verified) { + Drawable verifiedBackground = context.getResources().getDrawable(R.drawable.verified_area).mutate(); + verifiedBackground.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_verifiedBackground), PorterDuff.Mode.MULTIPLY)); + Drawable verifiedCheck = context.getResources().getDrawable(R.drawable.verified_check).mutate(); + verifiedCheck.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_verifiedCheck), PorterDuff.Mode.MULTIPLY)); + Drawable verifiedDrawable = new CombinedDrawable(verifiedBackground, verifiedCheck); + textView.setRightDrawable(verifiedDrawable); + } + + TextView subtitleView = new TextView(context); + subtitleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue)); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleView.setLines(1); + subtitleView.setMaxLines(1); + subtitleView.setSingleLine(true); + subtitleView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + subtitleView.setEllipsize(TextUtils.TruncateAt.END); + subtitleView.setOnClickListener(v -> { + Bundle args = new Bundle(); + args.putLong("user_id", user.id); + if (fragment.getMessagesController().checkCanOpenChat(args, fragment)) { + fragment.presentFragment(new ProfileActivity(args)); + } + + builder.getDismissRunnable().run(); + }); + SpannableString ssb = SpannableString.valueOf(LocaleController.getString(R.string.MoreAboutThisBot) + " "); + ColoredImageSpan img = new ColoredImageSpan(R.drawable.attach_arrow_right); + img.setTopOffset(1); + img.setSize(dp(10)); + ssb.setSpan(img, ssb.length() - 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + subtitleView.setText(ssb); + + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 0, (LocaleController.isRTL ? 76 : 21), 0)); + frameLayout.addView(subtitleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 24, (LocaleController.isRTL ? 76 : 21), 0)); frameLayout.addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 57, 24, 1)); if (user != null) { @@ -1505,7 +1553,7 @@ public void setText(CharSequence text, BufferType type) { } }); - messageTextView.setText(AndroidUtilities.replaceSingleTag(getString(R.string.BotWebViewStartPermission), () -> { + messageTextView.setText(AndroidUtilities.replaceSingleTag(getString(R.string.BotWebViewStartPermission2), () -> { if (dialog != null) { dialog.dismiss(); } @@ -1553,16 +1601,21 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { imageView.setRoundRadius(dp(20)); frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 22, 5, 22, 0)); - TextView titleView = new TextView(context); + SimpleTextView titleView = new SimpleTextView(context); titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); - titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTextSize(20); titleView.setTypeface(AndroidUtilities.bold()); - titleView.setLines(1); - titleView.setMaxLines(1); - titleView.setSingleLine(true); titleView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - titleView.setEllipsize(TextUtils.TruncateAt.END); + titleView.setEllipsizeByGradient(true); titleView.setText(user.first_name); + if (user.verified) { + Drawable verifiedBackground = context.getResources().getDrawable(R.drawable.verified_area).mutate(); + verifiedBackground.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_verifiedBackground), PorterDuff.Mode.MULTIPLY)); + Drawable verifiedCheck = context.getResources().getDrawable(R.drawable.verified_check).mutate(); + verifiedCheck.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_verifiedCheck), PorterDuff.Mode.MULTIPLY)); + Drawable verifiedDrawable = new CombinedDrawable(verifiedBackground, verifiedCheck); + titleView.setRightDrawable(verifiedDrawable); + } TextView subtitleView = new TextView(context); subtitleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue)); @@ -1576,7 +1629,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Bundle args = new Bundle(); args.putLong("user_id", user.id); if (fragment.getMessagesController().checkCanOpenChat(args, fragment)) { - fragment.presentFragment(new ChatActivity(args)); + fragment.presentFragment(new ProfileActivity(args)); } builder.getDismissRunnable().run(); @@ -1589,7 +1642,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { subtitleView.setText(ssb); frameLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 0, (LocaleController.isRTL ? 76 : 21), 0)); - frameLayout.addView(subtitleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 28, (LocaleController.isRTL ? 76 : 21), 0)); + frameLayout.addView(subtitleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 24, (LocaleController.isRTL ? 76 : 21), 0)); frameLayout.addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 57, 24, 1)); if (allowWrite != null) { @@ -1598,7 +1651,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { cell[0] = new CheckBoxCell(context, 1, fragment.getResourceProvider()); cell[0].allowMultiline(); cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false)); - cell[0].setText(AndroidUtilities.replaceTags(LocaleController.formatString("OpenUrlOption2", R.string.OpenUrlOption2, UserObject.getUserName(user))), "", true, false); + cell[0].setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.OpenUrlOption2, UserObject.getUserName(user))), "", true, false); cell[0].setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0); cell[0].setChecked(true, false); frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); @@ -1626,7 +1679,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { AlertDialog dialog = builder.create(); fragment.showDialog(dialog); - messageTextView.setText(AndroidUtilities.replaceSingleTag(getString(R.string.BotWebViewStartPermission), () -> { + messageTextView.setText(AndroidUtilities.replaceSingleTag(getString(R.string.BotWebViewStartPermission2), () -> { if (dialog != null) { dialog.dismiss(); } @@ -1942,6 +1995,85 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } } + public static void createClearOrDeleteDialogsAlert(BaseFragment fragment, boolean clear, boolean canDeleteHistory, int canClearCacheCount, int count, boolean hasDialogsToRevoke, MessagesStorage.BooleanCallback onProcessRunnable, Theme.ResourcesProvider resourcesProvider) { + int account = fragment.getCurrentAccount(); + + Context context = fragment.getParentActivity(); + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + long selfUserId = UserConfig.getInstance(account).getClientUserId(); + + CheckBoxCell[] cell = new CheckBoxCell[1]; + boolean[] deleteForAll = new boolean[1]; + TextView messageTextView = new TextView(context); + messageTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + messageTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); + FrameLayout frameLayout = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (cell[0] != null) { + setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() + cell[0].getMeasuredHeight() + dp(7)); + } + } + }; + builder.setCustomViewOffset(6); + builder.setView(frameLayout); + + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setTypeface(AndroidUtilities.bold()); + textView.setLines(1); + textView.setMaxLines(1); + textView.setSingleLine(true); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setEllipsize(TextUtils.TruncateAt.END); + if (canDeleteHistory) { + if (hasDialogsToRevoke) { + cell[0] = new CheckBoxCell(context, 1, resourcesProvider); + cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false)); + cell[0].setText(LocaleController.getString(R.string.DeleteMessagesForBothSidesWherePossible), "", false, false); + cell[0].setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0); + frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); + cell[0].setOnClickListener(v -> { + CheckBoxCell cell1 = (CheckBoxCell) v; + deleteForAll[0] = !deleteForAll[0]; + cell1.setChecked(deleteForAll[0], true); + }); + } + textView.setText(LocaleController.formatString("DeleteFewChatsTitle", R.string.DeleteFewChatsTitle, LocaleController.formatPluralString("ChatsSelected", count))); + messageTextView.setText(LocaleController.getString("AreYouSureDeleteFewChats", R.string.AreYouSureDeleteFewChats)); + } else { + if (canClearCacheCount != 0) { + textView.setText(LocaleController.formatString("ClearCacheFewChatsTitle", R.string.ClearCacheFewChatsTitle, LocaleController.formatPluralString("ChatsSelectedClearCache", count))); + messageTextView.setText(LocaleController.getString("AreYouSureClearHistoryCacheFewChats", R.string.AreYouSureClearHistoryCacheFewChats)); + } else { + textView.setText(LocaleController.formatString("ClearFewChatsTitle", R.string.ClearFewChatsTitle, LocaleController.formatPluralString("ChatsSelectedClear", count))); + messageTextView.setText(LocaleController.getString("AreYouSureClearHistoryFewChats", R.string.AreYouSureClearHistoryFewChats)); + } + } + + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 11, 24, 0)); + frameLayout.addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 57, 24, 1)); + + String actionText = canDeleteHistory ? LocaleController.getString("Delete", R.string.Delete) + : canClearCacheCount != 0 ? LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache) + : LocaleController.getString("ClearHistory", R.string.ClearHistory); + builder.setPositiveButton(actionText, (dialogInterface, i) -> { + if (onProcessRunnable != null) { + onProcessRunnable.run(deleteForAll[0]); + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + AlertDialog alertDialog = builder.create(); + fragment.showDialog(alertDialog); + TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); + } + } + public static void createClearDaysDialogAlert(BaseFragment fragment, int days, TLRPC.User user, TLRPC.Chat chat, boolean canDeleteHistory, MessagesStorage.BooleanCallback onProcessRunnable, Theme.ResourcesProvider resourcesProvider) { if (fragment == null || fragment.getParentActivity() == null || (user == null && chat == null)) { return; @@ -2017,7 +2149,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (chat != null && canDeleteHistory && ChatObject.isPublic(chat)) { deleteForAll[0] = true; } - if ((user != null && user.id != selfUserId) || (chat != null && canDeleteHistory && !ChatObject.isPublic(chat) && !ChatObject.isChannelAndNotMegaGroup(chat))) { + if ((user != null && user.id != selfUserId && user.id != UserObject.VERIFY) || (chat != null && canDeleteHistory && !ChatObject.isPublic(chat) && !ChatObject.isChannelAndNotMegaGroup(chat))) { cell[0] = new CheckBoxCell(context, 1, resourcesProvider); cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (chat != null) { @@ -4727,265 +4859,6 @@ public static BottomSheet createMuteAlert(BaseFragment fragment, ArrayList return builder.create(); } - public static void sendReport(TLRPC.InputPeer peer, int type, String message, ArrayList messages, int storyId) { - TLRPC.ReportReason reason = null; - if (type == AlertsCreator.REPORT_TYPE_SPAM) { - reason = new TLRPC.TL_inputReportReasonSpam(); - } else if (type == AlertsCreator.REPORT_TYPE_FAKE_ACCOUNT) { - reason = new TLRPC.TL_inputReportReasonFake(); - } else if (type == AlertsCreator.REPORT_TYPE_VIOLENCE) { - reason = new TLRPC.TL_inputReportReasonViolence(); - } else if (type == AlertsCreator.REPORT_TYPE_CHILD_ABUSE) { - reason = new TLRPC.TL_inputReportReasonChildAbuse(); - } else if (type == AlertsCreator.REPORT_TYPE_PORNOGRAPHY) { - reason = new TLRPC.TL_inputReportReasonPornography(); - } else if (type == AlertsCreator.REPORT_TYPE_ILLEGAL_DRUGS) { - reason = new TLRPC.TL_inputReportReasonIllegalDrugs(); - } else if (type == AlertsCreator.REPORT_TYPE_PERSONAL_DETAILS) { - reason = new TLRPC.TL_inputReportReasonPersonalDetails(); - } else if (type == AlertsCreator.REPORT_TYPE_OTHER) { - reason = new TLRPC.TL_inputReportReasonOther(); - } - if (reason == null) { - return; - } - if (storyId != 0) { - TL_stories.TL_stories_report request = new TL_stories.TL_stories_report(); - request.peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(peer.user_id); - request.id.add(storyId); - request.message = message; - request.reason = reason; - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> { - - }); - } else { - TLRPC.TL_messages_report request = new TLRPC.TL_messages_report(); - request.peer = peer; - request.id.addAll(messages); - request.message = message; - request.reason = reason; - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> { - - }); - } - } - - public static void createReportAlert(final Context context, final long dialog_id, final int messageId, final BaseFragment parentFragment, Runnable hideDim) { - createReportAlert(context, dialog_id, messageId, 0, parentFragment, null, hideDim); - } - - public final static int REPORT_TYPE_SPAM = 0; - public final static int REPORT_TYPE_VIOLENCE = 1; - public final static int REPORT_TYPE_CHILD_ABUSE = 2; - public final static int REPORT_TYPE_ILLEGAL_DRUGS = 3; - public final static int REPORT_TYPE_PERSONAL_DETAILS = 4; - public final static int REPORT_TYPE_PORNOGRAPHY = 5; - public final static int REPORT_TYPE_FAKE_ACCOUNT = 6; - public final static int REPORT_TYPE_OTHER = 100; - - public static void createReportAlert(final Context context, final long dialog_id, final int messageId, final int storyId, final BaseFragment parentFragment, Theme.ResourcesProvider resourcesProvider, Runnable hideDim) { - if (context == null || parentFragment == null) { - return; - } - - final TLRPC.User user = MessagesController.getInstance(parentFragment.getCurrentAccount()).getUser(dialog_id); - final boolean isBot = user != null && user.bot; - - BottomSheet.Builder builder = new BottomSheet.Builder(context, true, resourcesProvider); - builder.setDimBehind(hideDim == null); - builder.setOnPreDismissListener(di -> { - if (hideDim != null) { - hideDim.run(); - } - }); - builder.setTitle(LocaleController.getString(R.string.ReportChat), true); - CharSequence[] items; - int[] icons; - int[] types; - if (messageId != 0) { - - items = new CharSequence[]{ - LocaleController.getString(R.string.ReportChatSpam), - LocaleController.getString(R.string.ReportChatViolence), - LocaleController.getString(R.string.ReportChatChild), - LocaleController.getString(R.string.ReportChatIllegalDrugs), - LocaleController.getString(R.string.ReportChatPersonalDetails), - LocaleController.getString(R.string.ReportChatPornography), - LocaleController.getString(R.string.ReportChatOther) - }; - icons = new int[]{ - R.drawable.msg_clearcache, - R.drawable.msg_report_violence, - R.drawable.msg_block2, - R.drawable.msg_report_drugs, - R.drawable.msg_report_personal, - R.drawable.msg_report_xxx, - R.drawable.msg_report_other - }; - types = new int[]{ - REPORT_TYPE_SPAM, - REPORT_TYPE_VIOLENCE, - REPORT_TYPE_CHILD_ABUSE, - REPORT_TYPE_ILLEGAL_DRUGS, - REPORT_TYPE_PERSONAL_DETAILS, - REPORT_TYPE_PORNOGRAPHY, - REPORT_TYPE_OTHER - }; - } else { - items = new CharSequence[]{ - LocaleController.getString(R.string.ReportChatSpam), - LocaleController.getString(R.string.ReportChatFakeAccount), - LocaleController.getString(R.string.ReportChatViolence), - LocaleController.getString(R.string.ReportChatChild), - LocaleController.getString(R.string.ReportChatIllegalDrugs), - LocaleController.getString(R.string.ReportChatPersonalDetails), - LocaleController.getString(R.string.ReportChatPornography), - LocaleController.getString(R.string.ReportChatOther) - }; - icons = new int[]{ - R.drawable.msg_clearcache, - R.drawable.msg_report_fake, - R.drawable.msg_report_violence, - R.drawable.msg_block2, - R.drawable.msg_report_drugs, - R.drawable.msg_report_personal, - R.drawable.msg_report_xxx, - R.drawable.msg_report_other - }; - types = new int[]{ - REPORT_TYPE_SPAM, - REPORT_TYPE_FAKE_ACCOUNT, - REPORT_TYPE_VIOLENCE, - REPORT_TYPE_CHILD_ABUSE, - REPORT_TYPE_ILLEGAL_DRUGS, - REPORT_TYPE_PERSONAL_DETAILS, - REPORT_TYPE_PORNOGRAPHY, - REPORT_TYPE_OTHER - }; - } - builder.setItems(items, icons, (dialogInterface, i) -> { - int type = types[i]; - if (messageId == 0 && (type == REPORT_TYPE_SPAM || type == REPORT_TYPE_VIOLENCE || type == REPORT_TYPE_CHILD_ABUSE || type == REPORT_TYPE_PORNOGRAPHY || type == REPORT_TYPE_ILLEGAL_DRUGS || type == REPORT_TYPE_PERSONAL_DETAILS) && parentFragment instanceof ChatActivity && !isBot) { - ((ChatActivity) parentFragment).openReportChat(type); - return; - } else if (messageId == 0 && (type == REPORT_TYPE_OTHER || type == REPORT_TYPE_FAKE_ACCOUNT) || messageId != 0 && type == REPORT_TYPE_OTHER) { - if (parentFragment instanceof ChatActivity) { - AndroidUtilities.requestAdjustNothing(parentFragment.getParentActivity(), parentFragment.getClassGuid()); - } - parentFragment.showDialog(new ReportAlert(context, type, resourcesProvider) { - - @Override - public void dismissInternal() { - super.dismissInternal(); - if (parentFragment instanceof ChatActivity) { - ((ChatActivity) parentFragment).checkAdjustResize(); - } - } - - @Override - protected void onSend(int type, String message) { - ArrayList ids = new ArrayList<>(); - if (messageId != 0) { - ids.add(messageId); - } - TLRPC.InputPeer peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(dialog_id); - sendReport(peer, type, message, ids, storyId); - if (parentFragment instanceof ChatActivity) { - UndoView undoView = ((ChatActivity) parentFragment).getUndoView(); - if (undoView != null) { - undoView.showWithAction(0, UndoView.ACTION_REPORT_SENT, null); - } - } else { - AndroidUtilities.runOnUIThread(() -> { - BulletinFactory bulletinFactory = BulletinFactory.global(); - if (bulletinFactory != null) { - bulletinFactory.createReportSent(resourcesProvider).show(); - } - }); - } - } - }); - return; - } - TLObject req; - TLRPC.InputPeer peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(dialog_id); - if (storyId != 0) { - TL_stories.TL_stories_report request = new TL_stories.TL_stories_report(); - request.id.add(storyId); - request.peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(dialog_id); - request.message = ""; - if (type == REPORT_TYPE_SPAM) { - request.reason = new TLRPC.TL_inputReportReasonSpam(); - } else if (type == REPORT_TYPE_FAKE_ACCOUNT) { - request.reason = new TLRPC.TL_inputReportReasonFake(); - } else if (type == REPORT_TYPE_VIOLENCE) { - request.reason = new TLRPC.TL_inputReportReasonViolence(); - } else if (type == REPORT_TYPE_CHILD_ABUSE) { - request.reason = new TLRPC.TL_inputReportReasonChildAbuse(); - } else if (type == REPORT_TYPE_PORNOGRAPHY) { - request.reason = new TLRPC.TL_inputReportReasonPornography(); - } else if (type == REPORT_TYPE_ILLEGAL_DRUGS) { - request.reason = new TLRPC.TL_inputReportReasonIllegalDrugs(); - } else if (type == REPORT_TYPE_PERSONAL_DETAILS) { - request.reason = new TLRPC.TL_inputReportReasonPersonalDetails(); - } - req = request; - } else if (messageId != 0) { - TLRPC.TL_messages_report request = new TLRPC.TL_messages_report(); - request.peer = peer; - request.id.add(messageId); - request.message = ""; - if (type == REPORT_TYPE_SPAM) { - request.reason = new TLRPC.TL_inputReportReasonSpam(); - } else if (type == REPORT_TYPE_VIOLENCE) { - request.reason = new TLRPC.TL_inputReportReasonViolence(); - } else if (type == REPORT_TYPE_CHILD_ABUSE) { - request.reason = new TLRPC.TL_inputReportReasonChildAbuse(); - } else if (type == REPORT_TYPE_PORNOGRAPHY) { - request.reason = new TLRPC.TL_inputReportReasonPornography(); - } else if (type == REPORT_TYPE_ILLEGAL_DRUGS) { - request.reason = new TLRPC.TL_inputReportReasonIllegalDrugs(); - } else if (type == REPORT_TYPE_PERSONAL_DETAILS) { - request.reason = new TLRPC.TL_inputReportReasonPersonalDetails(); - } - req = request; - } else { - TLRPC.TL_account_reportPeer request = new TLRPC.TL_account_reportPeer(); - request.peer = peer; - request.message = ""; - if (type == REPORT_TYPE_SPAM) { - request.reason = new TLRPC.TL_inputReportReasonSpam(); - } else if (type == REPORT_TYPE_FAKE_ACCOUNT) { - request.reason = new TLRPC.TL_inputReportReasonFake(); - } else if (type == REPORT_TYPE_VIOLENCE) { - request.reason = new TLRPC.TL_inputReportReasonViolence(); - } else if (type == REPORT_TYPE_CHILD_ABUSE) { - request.reason = new TLRPC.TL_inputReportReasonChildAbuse(); - } else if (type == REPORT_TYPE_PORNOGRAPHY) { - request.reason = new TLRPC.TL_inputReportReasonPornography(); - } else if (type == REPORT_TYPE_ILLEGAL_DRUGS) { - request.reason = new TLRPC.TL_inputReportReasonIllegalDrugs(); - } else if (type == REPORT_TYPE_PERSONAL_DETAILS) { - request.reason = new TLRPC.TL_inputReportReasonPersonalDetails(); - } - req = request; - } - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> { - - }); - if (parentFragment instanceof ChatActivity) { - UndoView undoView = ((ChatActivity) parentFragment).getUndoView(); - if (undoView != null) { - undoView.showWithAction(0, UndoView.ACTION_REPORT_SENT, null); - } - } else { - BulletinFactory.of(parentFragment).createReportSent(resourcesProvider).show(); - } - }); - BottomSheet sheet = builder.create(); - parentFragment.showDialog(sheet); - } - private static String getFloodWaitString(String error) { int time = Utilities.parseInt(error); String timeString; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java index c07ae18821..39ff0e1a37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java @@ -6,6 +6,7 @@ import android.util.Property; import android.view.animation.OvershootInterpolator; +import org.telegram.messenger.ImageReceiver; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.PhotoViewer; @@ -65,6 +66,18 @@ public Integer get(Paint object) { } }; + public static final Property IMAGE_RECEIVER_ALPHA = new FloatProperty("currentAlpha") { + @Override + public void setValue(ImageReceiver object, float value) { + object.setCurrentAlpha(value); + } + + @Override + public Float get(ImageReceiver object) { + return object.getCurrentAlpha(); + } + }; + public static final Property COLOR_DRAWABLE_ALPHA = new IntProperty("alpha") { @Override public void setValue(ColorDrawable object, int value) { 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 cf7abda285..3b1cc8e06f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -7,6 +7,8 @@ import android.graphics.Canvas; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.os.Build; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -20,6 +22,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.ActionBar; @@ -91,6 +94,11 @@ public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, b this(context, fragment, needFocus, hasFixedSize, useNested, false, actionBarType, resourcesProvider); } + EditTextEmoji editTextEmoji; + public void setEditTextEmoji(EditTextEmoji editTextEmoji) { + this.editTextEmoji = editTextEmoji; + } + @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); @@ -98,7 +106,7 @@ public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, b this.hasFixedSize = hasFixedSize; this.stackFromEnd = stackFromEnd; headerShadowDrawable = ContextCompat.getDrawable(context, R.drawable.header_shadow).mutate(); - FrameLayout containerView; + SizeNotifierFrameLayout containerView; if (useNested) { containerView = nestedSizeNotifierLayout = new NestedSizeNotifierLayout(context) { @@ -140,44 +148,177 @@ public boolean dispatchTouchEvent(MotionEvent event) { } }; } else { - containerView = new FrameLayout(context) { - - @Override - 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); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - preDrawInternal(canvas, this); - super.dispatchDraw(canvas); - postDrawInternal(canvas, this); - } - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (!hasFixedSize && clipToActionBar && child == recyclerListView) { - canvas.save(); - canvas.clipRect(0, actionBar.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight()); - super.drawChild(canvas, child, drawingTime); - canvas.restore(); - return true; - } - return super.drawChild(canvas, child, drawingTime); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < shadowDrawable.getBounds().top) { - dismiss(); - } - return super.dispatchTouchEvent(event); - } + containerView = new SizeNotifierFrameLayout(context) { + private boolean ignoreLayout = false; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + contentHeight = MeasureSpec.getSize(heightMeasureSpec); + onPreMeasure(widthMeasureSpec, heightMeasureSpec); + if (stackFromEnd) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY); + } + if (editTextEmoji != null) { + onMeasureInternal(widthMeasureSpec, heightMeasureSpec); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + private void onMeasureInternal(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); +// widthSize -= backgroundPaddingLeft * 2; + + int keyboardSize = 0; + if (editTextEmoji != null && !editTextEmoji.isWaitingForKeyboardOpen() && keyboardSize <= AndroidUtilities.dp(20) && !editTextEmoji.isPopupShowing() && !editTextEmoji.isAnimatePopupClosing()) { + ignoreLayout = true; + editTextEmoji.hideEmojiView(); + ignoreLayout = false; + } + + if (keyboardSize <= AndroidUtilities.dp(20)) { + int paddingBottom = 0; + if (!keyboardVisible) { + if (editTextEmoji != null) { + paddingBottom = editTextEmoji.getEmojiPadding(); + } + } + if (!AndroidUtilities.isInMultiwindow) { + heightSize -= paddingBottom; + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); + } + } + + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE) { + continue; + } + if (editTextEmoji != null && editTextEmoji.isPopupView(child)) { +// if (inBubbleMode) { +// child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize + getPaddingTop(), MeasureSpec.EXACTLY)); +// } else + 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 { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + } + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + preDrawInternal(canvas, this); + super.dispatchDraw(canvas); + postDrawInternal(canvas, this); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (!hasFixedSize && clipToActionBar && child == recyclerListView) { + canvas.save(); + canvas.clipRect(0, actionBar.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight()); + super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < shadowDrawable.getBounds().top) { + dismiss(); + } + return super.dispatchTouchEvent(event); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (editTextEmoji == null) { + super.onLayout(changed, l, t, r, b); + return; + } + final int count = getChildCount(); + int keyboardSize = measureKeyboardHeight(); + int paddingBottom = getPaddingBottom(); + if (!keyboardVisible && editTextEmoji != null) { + if (keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + paddingBottom += editTextEmoji.getEmojiPadding(); + } + } + 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 - l) - width - lp.rightMargin - getPaddingRight() - backgroundPaddingLeft; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin + getPaddingLeft(); + } + + 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 (child instanceof EmojiView) { + if (AndroidUtilities.isTablet()) { + childTop = getMeasuredHeight() - child.getMeasuredHeight(); + } else { + childTop = getMeasuredHeight() + keyboardSize - child.getMeasuredHeight(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } }; } recyclerListView = new RecyclerListView(context, resourcesProvider) { @@ -282,6 +423,8 @@ public void setSlidingActionBar() { recyclerListView.setClipToPadding(true); } + public boolean reverseLayout; + protected void resetAdapter(Context context) { RecyclerListView.SelectionAdapter adapter = createAdapter(recyclerListView); RecyclerListView.SelectionAdapter wrapperAdapter = new RecyclerListView.SelectionAdapter() { @@ -324,17 +467,17 @@ public void setTranslationY(float translationY) { @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if (position != 0) { - adapter.onBindViewHolder(holder, position - 1); + if (position != (reverseLayout ? getItemCount() - 1 : 0)) { + adapter.onBindViewHolder(holder, position - (reverseLayout ? 0 : 1)); } } @Override public int getItemViewType(int position) { - if (position == 0) { + if (position == (reverseLayout ? getItemCount() - 1 : 0)) { return -1000; } - return adapter.getItemViewType(position - 1); + return adapter.getItemViewType(position - (reverseLayout ? 0 : 1)); } @Override @@ -352,27 +495,27 @@ public void onChanged() { @Override public void onItemRangeChanged(int positionStart, int itemCount) { - observer.onItemRangeChanged(positionStart + 1, itemCount); + observer.onItemRangeChanged(positionStart + (reverseLayout ? 0 : 1), itemCount); } @Override public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) { - observer.onItemRangeChanged(positionStart + 1, itemCount, payload); + observer.onItemRangeChanged(positionStart + (reverseLayout ? 0 : 1), itemCount, payload); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { - observer.onItemRangeInserted(positionStart + 1, itemCount); + observer.onItemRangeInserted(positionStart + (reverseLayout ? 0 : 1), itemCount); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { - observer.onItemRangeRemoved(positionStart + 1, itemCount); + observer.onItemRangeRemoved(positionStart + (reverseLayout ? 0 : 1), itemCount); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { - observer.onItemRangeMoved(fromPosition + 1, toPosition + 1, itemCount); + observer.onItemRangeMoved(fromPosition + (reverseLayout ? 0 : 1), toPosition + (reverseLayout ? 0 : 1), itemCount); } }); } @@ -406,19 +549,38 @@ private void postDrawInternal(Canvas canvas, View parentView) { headerShadowDrawable.draw(canvas); } } + if (restore) { + canvas.restore(); + restore = false; + } } + private boolean restore; private void preDrawInternal(Canvas canvas, View parent) { + restore = false; if (!hasFixedSize) { - RecyclerView.ViewHolder holder = recyclerListView.findViewHolderForAdapterPosition(0); - int top = -AndroidUtilities.dp(16); - if (holder != null) { - top = holder.itemView.getBottom() - AndroidUtilities.dp(16); - if (takeTranslationIntoAccount) { - top += (int) holder.itemView.getTranslationY(); + int top; + if (reverseLayout) { + top = recyclerListView.getHeight(); + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + View child = recyclerListView.getChildAt(i); + int pos = recyclerListView.getChildAdapterPosition(child); + if (pos != RecyclerView.NO_POSITION && pos != recyclerListView.getAdapter().getItemCount() - 1) { + top = Math.min(top, child.getTop() + (takeTranslationIntoAccount ? (int) child.getTranslationY() : 0)); + } + } + top -= AndroidUtilities.dp(16); + } else { + RecyclerView.ViewHolder holder = recyclerListView.findViewHolderForAdapterPosition(0); + 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; + top -= headerHeight + headerPaddingTop + headerPaddingBottom; if (showHandle && handleOffset) { top -= dp(actionBarType == ActionBarType.SLIDING ? 8 : 16); } @@ -434,6 +596,12 @@ private void preDrawInternal(Canvas canvas, View parent) { } 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); + + if (t != 0 && t != 1) { + canvas.save(); + canvas.clipRect(0, actionBarY, containerView.getMeasuredWidth(), containerView.getMeasuredHeight()); + restore = true; + } progressToFullView = t; shadowAlpha = t; handleAlpha = AndroidUtilities.lerp(1.0f, 0.5f, t); @@ -593,14 +761,16 @@ public void applyScrolledPosition() { } public void applyScrolledPosition(boolean ignorePaddingView) { - if (recyclerListView != null && layoutManager != null && savedScrollPosition >= 0) { + if (recyclerListView != null && recyclerListView.getLayoutManager() != 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); + if (recyclerListView.getLayoutManager() instanceof LinearLayoutManager) { + ((LinearLayoutManager) recyclerListView.getLayoutManager()).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 31f805440d..c5580b76f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -1329,6 +1329,14 @@ public void setAnimation(int resId, int w, int h, String... layers) { } } + public void setAnimation(TLRPC.Document document, int w, int h, String... layers) { + imageView.setAutoRepeat(true); + imageView.setAnimation(document, w, h); + for (String layer : layers) { + imageView.setLayerColor(layer + ".**", textColor); + } + } + public CharSequence getAccessibilityText() { return titleTextView.getText() + ".\n" + subtitleTextView.getText(); } 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 60e6f576e5..d72644a511 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -583,6 +583,29 @@ public Bulletin createEmojiBulletin(TLRPC.Document document, CharSequence text) return create(layout, Bulletin.DURATION_LONG); } + public Bulletin createEmojiBulletin(TLRPC.Document document, CharSequence text, CharSequence subtext) { + final Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(getContext(), resourcesProvider); + if (MessageObject.isTextColorEmoji(document)) { + layout.imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_undo_infoColor), PorterDuff.Mode.SRC_IN)); + } + layout.setAnimation(document, 36, 36); + layout.titleTextView.setText(text); + layout.subtitleTextView.setText(subtext); + return create(layout, (text.length() + subtext.length()) < 20 ? Bulletin.DURATION_SHORT : Bulletin.DURATION_LONG); + } + + public Bulletin createEmojiBulletin(TLRPC.Document document, CharSequence text, CharSequence subtext, CharSequence buttonText, Runnable onButtonClick) { + final Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(getContext(), resourcesProvider); + if (MessageObject.isTextColorEmoji(document)) { + layout.imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_undo_infoColor), PorterDuff.Mode.SRC_IN)); + } + layout.setAnimation(document, 36, 36); + layout.titleTextView.setText(text); + layout.subtitleTextView.setText(subtext); + layout.setButton(new Bulletin.UndoButton(getContext(), true, resourcesProvider).setText(buttonText).setUndoAction(onButtonClick)); + return create(layout, (text.length() + subtext.length()) < 20 ? Bulletin.DURATION_SHORT : Bulletin.DURATION_LONG); + } + public Bulletin createStaticEmojiBulletin(TLRPC.Document document, CharSequence text) { final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); if (MessageObject.isTextColorEmoji(document)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonSpan.java new file mode 100644 index 0000000000..0d7cc662ac --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonSpan.java @@ -0,0 +1,140 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.dpf2; +import static org.telegram.messenger.LocaleController.formatPluralString; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.Layout; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.ClickableSpan; +import android.text.style.ReplacementSpan; +import android.view.MotionEvent; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Business.QuickRepliesActivity; + +public class ButtonSpan extends ReplacementSpan { + + private final Theme.ResourcesProvider resourcesProvider; + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Text text; + private final Runnable onClickListener; + private ButtonBounce bounce; + + private ButtonSpan(CharSequence buttonText, Runnable onClick, Theme.ResourcesProvider resourcesProvider) { + this.resourcesProvider = resourcesProvider; + this.onClickListener = onClick; + text = new Text(buttonText, 12); + } + + public static CharSequence make(CharSequence buttonText, Runnable onClick) { + return make(buttonText, onClick, null); + } + + public static CharSequence make(CharSequence buttonText, Runnable onClick, Theme.ResourcesProvider resourcesProvider) { + SpannableString ss = new SpannableString("btn"); + ButtonSpan span1 = new ButtonSpan(buttonText, onClick, resourcesProvider); + ss.setSpan(span1, 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return ss; + } + + public int getSize() { + return (int) (this.text.getCurrentWidth() + dp(14)); + } + + @Override + public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) { + return getSize(); + } + + @Override + public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { + final float h = dpf2(17), cy = (top + bottom) / 2f; + AndroidUtilities.rectTmp.set(x, cy - h / 2f, x + getSize(), cy + h / 2f); + final float s = bounce == null ? 1f : bounce.getScale(.025f); + canvas.save(); + canvas.scale(s, s, AndroidUtilities.rectTmp.centerX(), AndroidUtilities.rectTmp.centerY()); + final int color = Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider); + backgroundPaint.setColor(Theme.multAlpha(color, .15f)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, h / 2, h / 2, backgroundPaint); + this.text.draw(canvas, x + dp(7), (top + bottom) / 2f, color, 1f); + canvas.restore(); + } + + public void setPressed(View view, boolean pressed) { + if (bounce == null) { + bounce = new ButtonBounce(view); + } + bounce.setPressed(pressed); + } + + public static class TextViewButtons extends LinkSpanDrawable.LinksTextView { + + public TextViewButtons(Context context) { + super(context); + } + + public TextViewButtons(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + } + + public ButtonSpan findSpan(float x, int y) { + if (!(getText() instanceof Spanned)) return null; + Layout layout = getLayout(); + if (layout == null) return null; + int line = layout.getLineForVertical(y); + int offset = layout.getOffsetForHorizontal(line, x); + Spanned spanned = (Spanned) getText(); + ButtonSpan[] spans = spanned.getSpans(layout.getLineStart(line), layout.getLineEnd(line), ButtonSpan.class); + for (int i = 0; i < spans.length; ++i) { + ButtonSpan span = spans[i]; + if (spanned.getSpanStart(span) <= offset && spanned.getSpanEnd(span) >= offset) { + return span; + } + } + return null; + } + + + private ButtonSpan pressedSpan; + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getAction(); + ButtonSpan span = findSpan(event.getX(), (int) event.getY()); + if (action == MotionEvent.ACTION_DOWN) { + pressedSpan = span; + if (pressedSpan != null) { + pressedSpan.setPressed(this, true); + return true; + } + } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (pressedSpan != null) { + pressedSpan.setPressed(this, false); + if (action == MotionEvent.ACTION_UP && pressedSpan.onClickListener != null) { + pressedSpan.onClickListener.run(); + } + } + pressedSpan = null; + } else if (action == MotionEvent.ACTION_MOVE) { + if (pressedSpan != null && pressedSpan != span) { + pressedSpan.setPressed(this, false); + pressedSpan = null; + } + } + return pressedSpan != null || super.onTouchEvent(event); + } + } +} \ No newline at end of file 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 acdfcb8fc4..3e9a366195 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -160,12 +160,11 @@ import org.telegram.ui.Business.BusinessLinksController; import org.telegram.ui.Business.QuickRepliesController; import org.telegram.ui.ChatActivity; -import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.boosts.BoostRepository; -import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftToUsersBottomSheet; import org.telegram.ui.ContentPreviewViewer; import org.telegram.ui.DialogsActivity; +import org.telegram.ui.Gifts.GiftSheet; import org.telegram.ui.GroupStickersActivity; import org.telegram.ui.LaunchActivity; import org.telegram.ui.MessageSendPreview; @@ -3253,20 +3252,18 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto ArrayList options = new ArrayList<>(getParentFragment().getCurrentUserInfo().premium_gifts); if (options.isEmpty()) { final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER); - final int reqId = BoostRepository.loadGiftOptions(null, loadedOptions -> { + final int reqId = BoostRepository.loadGiftOptions(currentAccount, null, loadedOptions -> { progressDialog.dismiss(); loadedOptions = BoostRepository.filterGiftOptions(loadedOptions, 1); loadedOptions = BoostRepository.filterGiftOptionsByBilling(loadedOptions); - ArrayList users = new ArrayList<>(); - users.add(user); - PremiumPreviewGiftToUsersBottomSheet.show(users, loadedOptions); + new GiftSheet(getContext(), currentAccount, user.id, loadedOptions, null).show(); }); progressDialog.setOnCancelListener(di -> { parentFragment.getConnectionsManager().cancelRequest(reqId, true); }); progressDialog.showDelayed(200); } else { - new GiftPremiumBottomSheet(getParentFragment(), getParentFragment().getCurrentUser()).show(); + new GiftSheet(getContext(), currentAccount, user.id, null, null).show(); } }); } @@ -9877,7 +9874,11 @@ public boolean didPressedBotButton(final TLRPC.KeyboardButton button, final Mess return false; } if (parentFragment != null && parentFragment.getChatMode() == ChatActivity.MODE_QUICK_REPLIES) return false; - if (button instanceof TLRPC.TL_keyboardButton) { + if (button instanceof TLRPC.TL_keyboardButtonCopy) { + final TLRPC.TL_keyboardButtonCopy btn = (TLRPC.TL_keyboardButtonCopy) button; + AndroidUtilities.addToClipboard(btn.copy_text); + BulletinFactory.of(parentFragment).createCopyBulletin(LocaleController.formatString(R.string.ExactTextCopied, btn.copy_text)).show(true); + } else if (button instanceof TLRPC.TL_keyboardButton) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(button.text, dialog_id, replyMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, null, false); params.quick_reply_shortcut = parentFragment != null ? parentFragment.quickReplyShortcut : null; params.quick_reply_shortcut_id = parentFragment != null ? parentFragment.getQuickReplyId() : 0; @@ -10353,7 +10354,7 @@ public void onClearEmojiRecent() { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity, resourcesProvider); builder.setTitle(getString(R.string.ClearRecentEmojiTitle)); builder.setMessage(getString(R.string.ClearRecentEmojiText)); - builder.setPositiveButton(getString(R.string.ClearForAll), (dialogInterface, i) -> emojiView.clearRecentEmoji()); + builder.setPositiveButton(getString(R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); builder.setNegativeButton(getString(R.string.Cancel), null); parentFragment.showDialog(builder.create()); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityInterface.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityInterface.java index a8ce41686b..2b463cebb7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityInterface.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityInterface.java @@ -41,6 +41,10 @@ default long getTopicId() { return 0; } + default boolean isRightFragment() { + return false; + } + ChatAvatarContainer getAvatarContainer(); default void checkAndUpdateAvatar() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java index f082246fde..0a24ec5466 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -164,7 +164,7 @@ public ChatAvatarContainer(Context context, BaseFragment baseFragment, boolean n parentFragment = (ChatActivity) baseFragment; } - final boolean avatarClickable = parentFragment != null && parentFragment.getChatMode() == 0 && !UserObject.isReplyUser(parentFragment.getCurrentUser()); + final boolean avatarClickable = parentFragment != null && parentFragment.getChatMode() == 0 && !UserObject.isReplyUser(parentFragment.getCurrentUser()) && (parentFragment.getCurrentUser() == null || parentFragment.getCurrentUser().id != UserObject.VERIFY); avatarImageView = new BackupImageView(context) { StoriesUtilities.AvatarStoryParams params = new StoriesUtilities.AvatarStoryParams(true) { @@ -325,7 +325,7 @@ public boolean onTouchEvent(MotionEvent event) { } if (parentFragment != null && (parentFragment.getChatMode() == 0 || parentFragment.getChatMode() == ChatActivity.MODE_SAVED)) { - if ((!parentFragment.isThreadChat() || parentFragment.isTopic) && !UserObject.isReplyUser(parentFragment.getCurrentUser())) { + if ((!parentFragment.isThreadChat() || parentFragment.isTopic || parentFragment.isComments) && !UserObject.isReplyUser(parentFragment.getCurrentUser()) && (parentFragment.getCurrentUser() == null || parentFragment.getCurrentUser().id != UserObject.VERIFY)) { setOnClickListener(v -> { openProfile(false); }); @@ -377,6 +377,12 @@ public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(ev); } + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + bounce.setPressed(pressed); + } + @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); @@ -509,7 +515,16 @@ public void openProfile(boolean byAvatar, boolean fromChatAnimation, boolean rem } } + if (parentFragment.isComments) { + if (chat == null) return; + parentFragment.presentFragment(ProfileActivity.of(-chat.id), removeLast); + return; + } + if (user != null) { + if (user.id == UserObject.VERIFY) { + return; + } Bundle args = new Bundle(); if (UserObject.isUserSelf(user)) { if (!sharedMediaPreloader.hasSharedMedia()) { @@ -940,7 +955,7 @@ public void updateSubtitle(boolean animated) { return; } TLRPC.User user = parentFragment.getCurrentUser(); - if ((UserObject.isUserSelf(user) || UserObject.isReplyUser(user) || parentFragment.getChatMode() != 0) && parentFragment.getChatMode() != ChatActivity.MODE_SAVED) { + if ((UserObject.isUserSelf(user) || UserObject.isReplyUser(user) || user != null && user.id == UserObject.VERIFY || parentFragment.getChatMode() != 0) && parentFragment.getChatMode() != ChatActivity.MODE_SAVED) { if (getSubtitleTextView().getVisibility() != GONE) { getSubtitleTextView().setVisibility(GONE); } @@ -1017,6 +1032,8 @@ public void onAnimationEnd(Animator animation) { String newStatus; if (UserObject.isReplyUser(user)) { newStatus = ""; + } else if (user.id == UserObject.VERIFY) { + newStatus = "";//LocaleController.getString(R.string.VerifyCodesNotifications); } else if (user.id == UserConfig.getInstance(currentAccount).getClientUserId()) { newStatus = LocaleController.getString(R.string.ChatYourSelf); } else if (user.id == 333000 || user.id == 777000 || user.id == 42777) { 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 632fdb0cb4..7649446ca4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java @@ -100,10 +100,7 @@ public ChatGreetingsView(Context context, TLRPC.User user, int currentAccount, T updateColors(); - titleView.setText(getString(R.string.NoMessages)); - descriptionView.setText(getString(R.string.NoMessagesGreetingsDescription)); - descriptionView.setMaxWidth(HintView2.cutInFancyHalf(descriptionView.getText(), descriptionView.getPaint())); - stickerToSendView.setContentDescription(descriptionView.getText()); + setText(getString(R.string.NoMessages), getString(R.string.NoMessagesGreetingsDescription)); preloadedGreetingsSticker = sticker; if (preloadedGreetingsSticker == null) { @@ -111,6 +108,13 @@ public ChatGreetingsView(Context context, TLRPC.User user, int currentAccount, T } } + public void setText(CharSequence title, CharSequence description) { + titleView.setText(title); + descriptionView.setText(description); + descriptionView.setMaxWidth(HintView2.cutInFancyHalf(descriptionView.getText(), descriptionView.getPaint())); + stickerToSendView.setContentDescription(descriptionView.getText()); + } + private RLottieImageView premiumIconView; private TextView premiumTextView; private TextView premiumButtonView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ContactsEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ContactsEmptyView.java index 6d833ac5a8..2e7b3deb48 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ContactsEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ContactsEmptyView.java @@ -8,7 +8,11 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.util.TypedValue; @@ -18,20 +22,24 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.Theme; import java.util.ArrayList; -public class ContactsEmptyView extends LinearLayout implements NotificationCenter.NotificationCenterDelegate { +public class ContactsEmptyView extends LinearLayout { private TextView titleTextView; + private TextView subtitleTextView; + private LinkSpanDrawable.LinksTextView buttonTextView; + private BackupImageView stickerView; private ArrayList textViews = new ArrayList<>(); private ArrayList imageViews = new ArrayList<>(); @@ -39,8 +47,6 @@ public class ContactsEmptyView extends LinearLayout implements NotificationCente private int currentAccount = UserConfig.selectedAccount; - private static final String stickerSetName = AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME; - public static final String svg = "m418 282.6c13.4-21.1 20.2-44.9 20.2-70.8 0-88.3-79.8-175.3-178.9-175.3-100.1 0-178.9 88-178.9 175.3 0 46.6 16.9 73.1 29.1 86.1-19.3 23.4-30.9 52.3-34.6 86.1-2.5 22.7 3.2 41.4 17.4 57.3 14.3 16 51.7 35 148.1 35 41.2 0 119.9-5.3 156.7-18.3 49.5-17.4 59.2-41.1 59.2-76.2 0-41.5-12.9-74.8-38.3-99.2z"; public ContactsEmptyView(Context context) { super(context); @@ -56,52 +62,44 @@ public ContactsEmptyView(Context context) { } titleTextView = new TextView(context); - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); titleTextView.setGravity(Gravity.CENTER_HORIZONTAL); - titleTextView.setText(LocaleController.getString(R.string.NoContactsYet)); + titleTextView.setText(LocaleController.getString(R.string.NoContactsYet2)); titleTextView.setTypeface(AndroidUtilities.bold()); - titleTextView.setMaxWidth(AndroidUtilities.dp(260)); - addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 18, 0, 14)); - - LinearLayout linesContainer = new LinearLayout(context); - linesContainer.setOrientation(VERTICAL); - addView(linesContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); - - for (int a = 0; a < 3; a++) { - if (a == 1) continue; - LinearLayout linearLayout = new LinearLayout(context); - linearLayout.setOrientation(LinearLayout.HORIZONTAL); - linesContainer.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 8, 0, 0)); - - ImageView imageView = new ImageView(context); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText), PorterDuff.Mode.MULTIPLY)); - imageView.setImageResource(R.drawable.list_circle); - imageViews.add(imageView); - - TextView textView = new TextView(context); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); - textView.setMaxWidth(AndroidUtilities.dp(260)); - textViews.add(textView); - textView.setGravity(Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - - switch (a) { - case 0: - textView.setText(LocaleController.getString(R.string.NoContactsYetLine1)); - break; - case 2: - textView.setText(LocaleController.getString(R.string.NoContactsYetLine3)); - break; - } - if (LocaleController.isRTL) { - linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 8, 7, 0, 0)); - } else { - linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 8, 8, 0)); - linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - } - } + addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 18, 0, 9)); + + subtitleTextView = new TextView(context); + subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + subtitleTextView.setGravity(Gravity.CENTER_HORIZONTAL); + subtitleTextView.setText(LocaleController.getString(R.string.NoContactsYet2Sub)); + subtitleTextView.setMaxWidth(AndroidUtilities.dp(260)); + addView(subtitleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 14)); + + buttonTextView = new LinkSpanDrawable.LinksTextView(context); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + buttonTextView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn)); + buttonTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + buttonTextView.setGravity(Gravity.CENTER_HORIZONTAL); + buttonTextView.setPadding(dp(8), dp(2), dp(2), dp(8)); + buttonTextView.setDisablePaddingsOffsetY(true); + buttonTextView.setText(AndroidUtilities.replaceArrows(AndroidUtilities.makeClickable(LocaleController.getString(R.string.NoContactsYet2Invite), () -> { + onInviteClick(); + }), true, dp(8f / 3f), dp(1))); + buttonTextView.setMaxWidth(AndroidUtilities.dp(260)); + addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 14)); + } + + protected void onInviteClick() { + Activity activity = AndroidUtilities.findActivity(getContext()); + if (activity == null || activity.isFinishing()) return; + + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + String text = ContactsController.getInstance(currentAccount).getInviteText(0); + intent.putExtra(Intent.EXTRA_TEXT, text); + activity.startActivityForResult(Intent.createChooser(intent, text), 500); } public void setColors() { @@ -115,40 +113,12 @@ public void setColors() { } private void setSticker() { - TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccount).getStickerSetByName(stickerSetName); - if (set == null) { - set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(stickerSetName); - } - if (set != null && set.documents.size() >= 1) { - TLRPC.Document document = set.documents.get(0); - ImageLocation imageLocation = ImageLocation.getForDocument(document); - stickerView.setImage(imageLocation, "130_130", "tgs", drawable, set); - } else { - MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(stickerSetName, false, true); - stickerView.setImageDrawable(drawable); - } + stickerView.setImageDrawable(new RLottieDrawable(R.raw.utyan_empty, "utyan_empty", dp(130), dp(130))); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); setSticker(); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.diceStickersDidLoad); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.diceStickersDidLoad); - } - - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.diceStickersDidLoad) { - String name = (String) args[0]; - if (stickerSetName.equals(name)) { - setSticker(); - } - } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateGroupCallBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateGroupCallBottomSheet.java index 2f63e81552..b96fbcbc25 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateGroupCallBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateGroupCallBottomSheet.java @@ -1,9 +1,12 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.os.Build; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -28,7 +31,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.GroupCreateUserCell; import org.telegram.ui.Cells.HeaderCell; -import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; import java.util.ArrayList; import java.util.List; @@ -36,7 +39,7 @@ public class CreateGroupCallBottomSheet extends BottomSheetWithRecyclerListView { private static final int HOLDER_TYPE_HEADER = 0, - HOLDER_TYPE_DIVIDER = 1, + HOLDER_TYPE_SHADOW_TEXT = 1, HOLDER_TYPE_SUBTITLE = 2, HOLDER_TYPE_USER = 3; @@ -62,10 +65,14 @@ public static void show(ArrayList peers, BaseFragment fragment, long private boolean isScheduleSelected; private TLRPC.Peer selectedPeer; private TLRPC.InputPeer selectAfterDismiss; + private final BaseFragment fragment; + private final long dialogId; public CreateGroupCallBottomSheet(BaseFragment fragment, ArrayList arrayList, long dialogId, JoinCallAlert.JoinCallAlertDelegate joinCallDelegate) { super(fragment, false, false); TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + this.fragment = fragment; + this.dialogId = dialogId; this.topPadding = 0.26f; this.chats = new ArrayList<>(arrayList); this.joinCallDelegate = joinCallDelegate; @@ -152,7 +159,7 @@ protected void onDraw(Canvas canvas) { public void dismissInternal() { super.dismissInternal(); if (selectAfterDismiss != null) { - joinCallDelegate.didSelectChat(selectAfterDismiss, chats.size() > 1, isScheduleSelected); + joinCallDelegate.didSelectChat(selectAfterDismiss, chats.size() > 1, isScheduleSelected, false); } } @@ -183,15 +190,19 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int case HOLDER_TYPE_HEADER: view = new TopCell(context, isChannelOrGiga); break; - case HOLDER_TYPE_DIVIDER: - view = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray)); - break; case HOLDER_TYPE_SUBTITLE: view = new HeaderCell(context, 22); break; case HOLDER_TYPE_USER: view = new GroupCreateUserCell(context, 1, 0, false); break; + case HOLDER_TYPE_SHADOW_TEXT: + TextInfoPrivacyCell cell = new TextInfoPrivacyCell(context); + cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + cell.setTopPadding(17); + cell.setBottomPadding(17); + view = cell; + break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); @@ -219,6 +230,12 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi cell.setTextSize(15); cell.setPadding(0, 0, 0, AndroidUtilities.dp(2)); cell.setText(LocaleController.getString(R.string.VoipChatDisplayedAs).replace(":", "")); + } else if (holder.getItemViewType() == HOLDER_TYPE_SHADOW_TEXT) { + TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView; + CharSequence text = AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.VoipChatStreamWithAnotherApp), Theme.key_windowBackgroundWhiteBlueHeader, AndroidUtilities.REPLACING_TAG_TYPE_LINK, () -> { + CreateRtmpStreamBottomSheet.show(selectedPeer, fragment, dialogId, chats.size() > 1, joinCallDelegate); + }), true, dp(1), dp(1f)); + cell.setText(text); } } @@ -228,7 +245,7 @@ public int getItemViewType(int position) { case 0: return HOLDER_TYPE_HEADER; case 1: - return HOLDER_TYPE_DIVIDER; + return HOLDER_TYPE_SHADOW_TEXT; case 2: return HOLDER_TYPE_SUBTITLE; default: diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateRtmpStreamBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateRtmpStreamBottomSheet.java new file mode 100644 index 0000000000..eeeefe23f4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CreateRtmpStreamBottomSheet.java @@ -0,0 +1,183 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +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 android.widget.Toast; + +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextDetailCell; + +import java.util.ArrayList; + +public class CreateRtmpStreamBottomSheet extends BottomSheetWithRecyclerListView { + + private static final int CONTAINER_HEIGHT_DP = 72; + + public static void show(TLRPC.Peer peer, BaseFragment fragment, long dialogId, boolean hasFewPeers, JoinCallAlert.JoinCallAlertDelegate joinCallDelegate) { + CreateRtmpStreamBottomSheet alert = new CreateRtmpStreamBottomSheet(fragment, peer, dialogId, hasFewPeers, joinCallDelegate); + if (fragment != null && fragment.getParentActivity() != null) { + fragment.showDialog(alert); + } else { + alert.show(); + } + } + + private final JoinCallAlert.JoinCallAlertDelegate joinCallDelegate; + private TLRPC.InputPeer selectAfterDismiss; + private final boolean hasFewPeers; + private String rtmpUrl; + private String rtmpKey; + private UniversalAdapter adapter; + + public CreateRtmpStreamBottomSheet(BaseFragment fragment, TLRPC.Peer selectedPeer, long dialogId, boolean hasFewPeers, JoinCallAlert.JoinCallAlertDelegate joinCallDelegate) { + super(fragment, false, false); + this.topPadding = 0.26f; + this.joinCallDelegate = joinCallDelegate; + this.hasFewPeers = hasFewPeers; + Context context = containerView.getContext(); + TextView startBtn = new TextView(context); + startBtn.setGravity(Gravity.CENTER); + startBtn.setEllipsize(TextUtils.TruncateAt.END); + startBtn.setSingleLine(true); + startBtn.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + startBtn.setTypeface(AndroidUtilities.bold()); + startBtn.setText(LocaleController.getString(R.string.VoipChannelStartStreaming)); + startBtn.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + startBtn.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Theme.getColor(Theme.key_featuredStickers_addButton), ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhite), 120))); + containerView.addView(startBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM, 16, 0, 16, 12)); + + startBtn.setOnClickListener(view -> { + selectAfterDismiss = MessagesController.getInstance(currentAccount).getInputPeer(MessageObject.getPeerId(selectedPeer)); + dismiss(); + }); + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, AndroidUtilities.dp(CONTAINER_HEIGHT_DP)); + fixNavigationBar(); + updateTitle(); + + TLRPC.TL_phone_getGroupCallStreamRtmpUrl req = new TLRPC.TL_phone_getGroupCallStreamRtmpUrl(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.revoke = false; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response != null) { + if (response instanceof TLRPC.TL_phone_groupCallStreamRtmpUrl) { + TLRPC.TL_phone_groupCallStreamRtmpUrl rtmpUrl = (TLRPC.TL_phone_groupCallStreamRtmpUrl) response; + this.rtmpUrl = rtmpUrl.url; + this.rtmpKey = rtmpUrl.key; + adapter.update(false); + } + } + })); + } + + @Override + public void dismissInternal() { + super.dismissInternal(); + if (selectAfterDismiss != null) { + joinCallDelegate.didSelectChat(selectAfterDismiss, hasFewPeers, false, true); + } + } + + @Override + protected CharSequence getTitle() { + return LocaleController.getString(R.string.Streaming); + } + + @Override + public RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + adapter = new UniversalAdapter(listView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider); + return adapter; + } + + private void fillItems(ArrayList items, UniversalAdapter adapter) { + items.add(UItem.asCustom(new TopCell(getContext()))); + items.add(UItem.asShadow(null)); + items.add(UItem.asHeader(LocaleController.getString(R.string.VoipChatStreamSettings))); + items.add(TextDetailCellFactory.of(rtmpUrl, LocaleController.getString(R.string.VoipChatStreamServerUrl), true)); + items.add(TextDetailCellFactory.of(rtmpKey, LocaleController.getString(R.string.VoipChatStreamKey), false)); + items.add(UItem.asShadow(LocaleController.getString(R.string.VoipChatStreamWithAnotherAppDescription))); + } + + private static class TopCell extends LinearLayout { + + public TopCell(Context context) { + super(context); + setOrientation(LinearLayout.VERTICAL); + + RLottieImageView imageView = new RLottieImageView(context); + imageView.setAutoRepeat(true); + imageView.setAnimation(R.raw.utyan_streaming, 112, 112); + imageView.playAnimation(); + addView(imageView, LayoutHelper.createLinear(112, 112, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 24, 0, 0)); + + TextView title = new TextView(context); + title.setTypeface(AndroidUtilities.bold()); + title.setText(LocaleController.formatString(R.string.Streaming)); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 14, 0, 7)); + + TextView description = new TextView(context); + description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + description.setGravity(Gravity.CENTER_HORIZONTAL); + description.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + description.setText(LocaleController.formatString(R.string.VoipStreamStart)); + description.setLineSpacing(description.getLineSpacingExtra(), description.getLineSpacingMultiplier() * 1.1f); + addView(description, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 28, 0, 28, 17)); + } + } + + public static class TextDetailCellFactory extends UItem.UItemFactory { + static { setup(new TextDetailCellFactory()); } + @Override + public TextDetailCell createView(Context context, int currentAccount, int classGuid, Theme.ResourcesProvider resourcesProvider) { + TextDetailCell view = new TextDetailCell(context); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + Drawable drawable = ContextCompat.getDrawable(context, R.drawable.msg_copy).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader), PorterDuff.Mode.MULTIPLY)); + view.setImage(drawable); + view.setImageClickListener(v -> copyRtmpValue(context, view.textView.getText().toString())); + return view; + } + + @Override + public void bindView(View view, UItem item, boolean divider) { + ((TextDetailCell) view).setTextAndValue(item.text, item.textValue, !item.hideDivider); + } + + public static UItem of(String text, String value, boolean divider) { + UItem item = UItem.ofFactory(TextDetailCellFactory.class); + item.text = text; + item.textValue = value; + item.hideDivider = !divider; + item.enabled = false; + return item; + } + + private void copyRtmpValue(Context context, String value) { + AndroidUtilities.addToClipboard(value); + if (AndroidUtilities.shouldShowClipboardToast()) { + Toast.makeText(context, LocaleController.getString(R.string.TextCopied), Toast.LENGTH_SHORT).show(); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java index 497016657e..728ee62977 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java @@ -762,9 +762,18 @@ private int getRestrictToggleTextKey() { } } + private boolean banChecked; private void onRestrictionsChanged() { + if (restrict && banOrRestrict.isPresent()) { + banChecked = banOrRestrict.selectedCount > 0; + } if (restrict && banOrRestrict.isPresent() && banOrRestrict.selectedCount == 0) { banOrRestrict.toggleAllChecks(); + } else if (!restrict && banOrRestrict.isPresent() && banChecked != (banOrRestrict.selectedCount > 0)) { + banOrRestrict.toggleAllChecks(); + } + if (!restrict && banOrRestrict.isPresent()) { + banChecked = banOrRestrict.selectedCount > 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java index 7e88ac5475..909339c197 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -96,6 +96,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not public static final int STYLE_DIALOG = 1; public static final int STYLE_STORY = 2; public static final int STYLE_PHOTOVIEWER = 3; + public static final int STYLE_GIFT = 4; private boolean waitingForKeyboardOpen; private boolean isAnimatePopupClosing; @@ -268,6 +269,15 @@ protected void onSelectionChanged(int selStart, int selEnd) { setClipChildren(false); setClipToPadding(false); addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 40, 0, 24, 0)); + } else if (style == STYLE_GIFT) { + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + editText.setMaxLines(4); + editText.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + editText.setHintTextColor(getThemedColor(Theme.key_dialogTextHint)); + editText.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); + editText.setBackground(null); + editText.setPadding(0, dp(11), 0, dp(12)); + addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 14, 0, 48, 0)); } else { editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); editText.setMaxLines(4); @@ -297,6 +307,10 @@ protected void dispatchDraw(Canvas canvas) { emojiIconDrawable.setColorFilter(new PorterDuffColorFilter(0x8cffffff, PorterDuff.Mode.MULTIPLY)); emojiIconDrawable.setIcon(R.drawable.input_smile, false); addView(emojiButton, LayoutHelper.createFrame(40, 40, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); + } else if (style == STYLE_GIFT) { + emojiIconDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + emojiIconDrawable.setIcon(R.drawable.input_smile, false); + addView(emojiButton, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.RIGHT, 0, 0, 0, 0)); } else { emojiIconDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); emojiIconDrawable.setIcon(R.drawable.input_smile, false); @@ -423,6 +437,11 @@ public void hideEmojiView() { } } + private boolean allowEmojisForNonPremium; + public void allowEmojisForNonPremium(boolean allow) { + allowEmojisForNonPremium = allow; + } + public EmojiView getEmojiView() { return emojiView; } @@ -754,6 +773,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto } } }; + emojiView.allowEmojisForNonPremium(allowEmojisForNonPremium); emojiView.setVisibility(GONE); if (AndroidUtilities.isTablet()) { emojiView.setForseMultiwindowLayout(true); 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 5019a2543c..5bd8cd6e26 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -55,6 +55,7 @@ public class FlickerLoadingView extends View implements Theme.Colorable { public static final int STAR_TIER = 31; public static final int BROWSER_BOOKMARK = 32; public static final int STAR_SUBSCRIPTION = 33; + public static final int STAR_GIFT = 34; private int gradientWidth; private LinearGradient gradient; @@ -162,6 +163,10 @@ protected void onDraw(Canvas canvas) { paint = globalGradientView.paint; } + if (getViewType() == STAR_GIFT) { + parentXOffset = -getX(); + } + updateColors(); updateGradient(); @@ -850,6 +855,10 @@ protected void onDraw(Canvas canvas) { break; } } + } else if (getViewType() == STAR_GIFT) { + rectF.set(paddingLeft, paddingTop, getMeasuredWidth() - paddingLeft, getMeasuredHeight() - paddingTop); + rectF.inset(dp(3.33f), dp(4)); + canvas.drawRoundRect(rectF, dp(11), dp(11), paint); } invalidate(); } @@ -871,6 +880,9 @@ public void updateGradient() { if (width == 0) { width = getMeasuredWidth(); } + if (viewType == STAR_GIFT) { + width = Math.max(width, AndroidUtilities.displaySize.x); + } int height = parentHeight; if (height == 0) { height = getMeasuredHeight(); @@ -905,10 +917,17 @@ public void updateColors() { if (this.color1 != color1 || this.color0 != color0) { this.color0 = color0; this.color1 = color1; + if (viewType == STAR_GIFT) { + gradientWidth = AndroidUtilities.displaySize.x; + } else if (isSingleCell || viewType == MESSAGE_SEEN_TYPE || viewType == CHAT_THEMES_TYPE || viewType == QR_TYPE) { + gradientWidth = dp(200); + } else { + gradientWidth = dp(600); + } if (isSingleCell || viewType == MESSAGE_SEEN_TYPE || viewType == CHAT_THEMES_TYPE || viewType == QR_TYPE) { - gradient = new LinearGradient(0, 0, gradientWidth = dp(200), 0, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + gradient = new LinearGradient(0, 0, gradientWidth, 0, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); } else { - gradient = new LinearGradient(0, 0, 0, gradientWidth = dp(600), new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + gradient = new LinearGradient(0, 0, 0, gradientWidth, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); } paint.setShader(gradient); } @@ -984,6 +1003,8 @@ private int getCellHeight(int width) { return dp(48) + 1; case BROWSER_BOOKMARK: return dp(56) + 1; + case STAR_GIFT: + return dp(140); } return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java index 7c8c425559..e82267cace 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -26,7 +26,6 @@ import android.view.View; import androidx.core.content.FileProvider; -import androidx.exifinterface.media.ExifInterface; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -849,7 +848,7 @@ private void processBitmap(Bitmap bitmap, MessageObject avatarObject) { NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.filePreparingStarted); NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileNewChunkAvailable); - MediaController.getInstance().scheduleVideoConvert(avatarObject, true, true); + MediaController.getInstance().scheduleVideoConvert(avatarObject, true, true, false); uploadingImage = null; if (delegate != null) { delegate.didStartUpload(true); 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 344ef7ba1c..334644a580 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -2285,8 +2285,14 @@ public void run() { } long timestamp; if (shouldUseTimestamp) { - audioRecorder.getTimestamp(audioTimestamp, AudioTimestamp.TIMEBASE_MONOTONIC); - timestamp = audioTimestamp.nanoTime / 1000; + try { + audioRecorder.getTimestamp(audioTimestamp, AudioTimestamp.TIMEBASE_MONOTONIC); + timestamp = audioTimestamp.nanoTime / 1000; + } catch (Exception e) { + FileLog.e(e); + shouldUseTimestamp = false; + timestamp = audioPresentationTimeUs = System.nanoTime() / 1000; + } } else { timestamp = audioPresentationTimeUs; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java index f3773c7c1b..6869b62468 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java @@ -37,10 +37,8 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BillingController; -import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; @@ -52,6 +50,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; @@ -62,7 +61,6 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.UserCell; -import org.telegram.ui.ChatActivity; import org.telegram.ui.LaunchActivity; import org.telegram.ui.LinkEditActivity; import org.telegram.ui.ManageLinksActivity; @@ -1206,7 +1204,7 @@ public RevenueUserCell(Context context) { addView(layout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 18, 0, 18, 0)); } - public void setRevenue(TLRPC.TL_starsSubscriptionPricing pricing, int joined_date) { + public void setRevenue(TL_stars.TL_starsSubscriptionPricing pricing, int joined_date) { if (pricing == null) { priceView.setText(null); periodView.setText(null); @@ -1262,7 +1260,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ); } - public void set(TLRPC.TL_starsSubscriptionPricing pricing, int count) { + public void set(TL_stars.TL_starsSubscriptionPricing pricing, int count) { if (pricing == null) return; if (pricing.period == StarsController.PERIOD_MONTHLY) { titleView.setText(StarsIntroActivity.replaceStarsWithPlain(LocaleController.formatString(R.string.LinkRevenuePrice, pricing.amount) + (count > 0 ? " x " + count : ""), .8f)); @@ -1280,7 +1278,7 @@ public static BottomSheet showSubscriptionSheet( Context context, int currentAccount, long dialogId, - TLRPC.TL_starsSubscriptionPricing pricing, + TL_stars.TL_starsSubscriptionPricing pricing, TLRPC.TL_chatInviteImporter importer, TLRPC.ChannelParticipant participant, Theme.ResourcesProvider resourcesProvider 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 298faf726b..974149a811 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java @@ -441,6 +441,9 @@ public ItemOptions setScrimViewBackground(Drawable drawable) { public ItemOptions setGravity(int gravity) { this.gravity = gravity; + if (gravity == Gravity.RIGHT && swipeback && layout instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) { + ((ActionBarPopupWindow.ActionBarPopupWindowLayout) layout).swipeBackGravityRight = true; + } return this; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java index 81c74f7811..17e17ef5fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java @@ -105,7 +105,7 @@ public static void processDeletedChat(int account, long did) { } public interface JoinCallAlertDelegate { - void didSelectChat(TLRPC.InputPeer peer, boolean hasFewPeers, boolean schedule); + void didSelectChat(TLRPC.InputPeer peer, boolean hasFewPeers, boolean schedule, boolean isRtmpStream); } public class BottomSheetCell extends FrameLayout { @@ -237,7 +237,7 @@ public static void open(Context context, long did, AccountInstance accountInstan if (lastCachedAccount == accountInstance.getCurrentAccount() && lastCacheDid == did && cachedChats != null && SystemClock.elapsedRealtime() - lastCacheTime < 5 * 60 * 1000) { if (cachedChats.size() == 1 && type != TYPE_CREATE) { TLRPC.InputPeer peer = accountInstance.getMessagesController().getInputPeer(MessageObject.getPeerId(cachedChats.get(0))); - delegate.didSelectChat(peer, false, false); + delegate.didSelectChat(peer, false, false, false); } else { showAlert(context, did, cachedChats, fragment, type, scheduledPeer, delegate); } @@ -255,7 +255,7 @@ public static void open(Context context, long did, AccountInstance accountInstan TLRPC.TL_phone_joinAsPeers res = (TLRPC.TL_phone_joinAsPeers) response; if (res.peers.size() == 1) { TLRPC.InputPeer peer = accountInstance.getMessagesController().getInputPeer(MessageObject.getPeerId(res.peers.get(0))); - delegate.didSelectChat(peer, false, false); + delegate.didSelectChat(peer, false, false, false); return; } cachedChats = res.peers; @@ -591,7 +591,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { TLRPC.InputPeer peer = MessagesController.getInstance(currentAccount).getInputPeer(MessageObject.getPeerId(selectedPeer)); if (currentType == TYPE_DISPLAY) { if (selectedPeer != currentPeer) { - delegate.didSelectChat(peer, chats.size() > 1, false); + delegate.didSelectChat(peer, chats.size() > 1, false, false); } } else { selectAfterDismiss = peer; @@ -663,7 +663,7 @@ private void updateLayout() { public void dismissInternal() { super.dismissInternal(); if (selectAfterDismiss != null) { - delegate.didSelectChat(selectAfterDismiss, chats.size() > 1, schedule); + delegate.didSelectChat(selectAfterDismiss, chats.size() > 1, schedule, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java index 3ddba543bf..df9d346087 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java @@ -200,6 +200,12 @@ public static LinearLayout.LayoutParams createLinear(int width, int height, int return layoutParams; } + public static LinearLayout.LayoutParams createLinear(float width, float height, int gravity) { + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(getSize(width), getSize(height)); + layoutParams.gravity = gravity; + return layoutParams; + } + public static LinearLayout.LayoutParams createLinear(int width, int height, float weight) { return new LinearLayout.LayoutParams(getSize(width), getSize(height), weight); } 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 4dca854a7c..d7bdade0f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java @@ -739,6 +739,16 @@ public void setTextColor(ColorStateList colors) { super.setTextColor(colors); emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); } + + public boolean hasLinks() { + Layout textLayout = getLayout(); + if (textLayout == null) return false; + CharSequence text = textLayout.getText(); + if (!(text instanceof Spanned)) return false; + Spanned spanned = (Spanned) text; + ClickableSpan[] spans = spanned.getSpans(0, spanned.length(), ClickableSpan.class); + return spans != null && spans.length > 0; + } } public static class ClickableSmallTextView extends SimpleTextView { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LoadingSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LoadingSpan.java index 000b4180dc..44b2427f13 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LoadingSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LoadingSpan.java @@ -64,7 +64,15 @@ public void setView(View view) { private Paint paint; @Override - public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) { + public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fm) { + final Paint.FontMetrics paintFontMetrics = paint.getFontMetrics(); + if (fm != null) { + fm.ascent = (int) paintFontMetrics.ascent; + fm.bottom = (int) paintFontMetrics.bottom; + fm.descent = (int) paintFontMetrics.descent; + fm.leading = (int) paintFontMetrics.leading; + fm.top = (int) paintFontMetrics.top; + } this.paint = paint; if (paint != null && this.drawable.color1 == null && this.drawable.color2 == null) { drawable.setColors( 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 dc89aa480e..2d6c50bd12 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 @@ -23,7 +23,6 @@ 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; @@ -44,7 +43,6 @@ 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; @@ -71,7 +69,6 @@ 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; @@ -1370,7 +1367,7 @@ public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, Stri stickerUploader.finalPath = message.attachPath = StoryEntry.makeCacheFile(UserConfig.selectedAccount, "webm").getAbsolutePath(); stickerUploader.messageObject = new MessageObject(UserConfig.selectedAccount, message, (MessageObject) null, false, false); stickerUploader.messageObject.videoEditedInfo = videoEditedInfo; - MediaController.getInstance().scheduleVideoConvert(stickerUploader.messageObject, false, false); + MediaController.getInstance().scheduleVideoConvert(stickerUploader.messageObject, false, false, false); } else { FileLoader.getInstance(currentAccount).uploadFile(path, false, true, ConnectionsManager.FileTypeFile); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PermissionRequest.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PermissionRequest.java index 479ceea67a..73439a9bfb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PermissionRequest.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PermissionRequest.java @@ -55,7 +55,7 @@ public static void ensureEitherPermission(int iconResId, int stringResId, String } boolean needsPermissionRationale = false; for (String permission : checkPermissions) { - if (activity.shouldShowRequestPermissionRationale(permission)) { + if (!activity.shouldShowRequestPermissionRationale(permission)) { needsPermissionRationale = true; break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GiftPremiumBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GiftPremiumBottomSheet.java index 9c0d7108b9..8c61b399b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GiftPremiumBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GiftPremiumBottomSheet.java @@ -499,16 +499,22 @@ public void updateDrawState(TextPaint p) { public final static class GiftTier { public final TLRPC.TL_premiumGiftOption giftOption; + public final TLRPC.TL_premiumGiftCodeOption giftCodeOption; private int discount; private long pricePerMonth; private long pricePerMonthRegular; - private ProductDetails googlePlayProductDetails; + public ProductDetails googlePlayProductDetails; public int yOffset; public GiftTier(TLRPC.TL_premiumGiftOption giftOption) { this.giftOption = giftOption; + this.giftCodeOption = null; + } + public GiftTier(TLRPC.TL_premiumGiftCodeOption giftCodeOption) { + this.giftOption = null; + this.giftCodeOption = giftCodeOption; } public ProductDetails getGooglePlayProductDetails() { @@ -523,8 +529,16 @@ public void setPricePerMonthRegular(long pricePerMonthRegular) { this.pricePerMonthRegular = pricePerMonthRegular; } + public String getStoreProduct() { + if (giftOption != null) return giftOption.store_product; + if (giftCodeOption != null) return giftCodeOption.store_product; + return null; + } + public int getMonths() { - return giftOption.months; + if (giftOption != null) return giftOption.months; + if (giftCodeOption != null) return giftCodeOption.months; + return 1; } public int getDiscount() { @@ -548,14 +562,14 @@ public long getPricePerMonth() { if (pricePerMonth == 0) { long price = getPrice(); if (price != 0) { - pricePerMonth = price / giftOption.months; + pricePerMonth = price / getMonths(); } } return pricePerMonth; } public String getFormattedPricePerMonth() { - if (BuildVars.useInvoiceBilling() || giftOption.store_product == null) { + if (BuildVars.useInvoiceBilling() || giftOption != null && giftOption.store_product == null || giftCodeOption != null && giftCodeOption.store_product == null) { return BillingController.getInstance().formatCurrency(getPricePerMonth(), getCurrency()); } @@ -563,7 +577,7 @@ public String getFormattedPricePerMonth() { } public String getFormattedPrice() { - if (BuildVars.useInvoiceBilling() || giftOption.store_product == null) { + if (BuildVars.useInvoiceBilling() || giftOption != null && giftOption.store_product == null || giftCodeOption != null && giftCodeOption.store_product == null) { return BillingController.getInstance().formatCurrency(getPrice(), getCurrency()); } @@ -571,15 +585,27 @@ public String getFormattedPrice() { } public long getPrice() { - if (BuildVars.useInvoiceBilling() || giftOption.store_product == null) { - return giftOption.amount; + if (giftOption != null) { + if (BuildVars.useInvoiceBilling() || giftOption.store_product == null) { + return giftOption.amount; + } + } else if (giftCodeOption != null) { + if (BuildVars.useInvoiceBilling() || giftCodeOption.store_product == null) { + return giftCodeOption.amount; + } } return googlePlayProductDetails == null ? 0 : googlePlayProductDetails.getOneTimePurchaseOfferDetails().getPriceAmountMicros(); } public String getCurrency() { - if (BuildVars.useInvoiceBilling() || giftOption.store_product == null) { - return giftOption.currency; + if (giftOption != null) { + if (BuildVars.useInvoiceBilling() || giftOption.store_product == null) { + return giftOption.currency; + } + } else if (giftCodeOption != null) { + if (BuildVars.useInvoiceBilling() || giftCodeOption.store_product == null) { + return giftCodeOption.currency; + } } return googlePlayProductDetails == null ? "" : googlePlayProductDetails.getOneTimePurchaseOfferDetails().getPriceCurrencyCode(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java index 3b0f92c124..ec69a8f6c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java @@ -26,6 +26,7 @@ public class PremiumLockIconView extends ImageView { public static int TYPE_REACTIONS = 0; public static int TYPE_STICKERS_PREMIUM_LOCKED = 1; public static int TYPE_REACTIONS_LOCK = 2; + public static int TYPE_GIFT_LOCK = 3; private final int type; public boolean isEnter; @@ -56,6 +57,9 @@ public PremiumLockIconView(Context context, int type, Theme.ResourcesProvider re } else if (type == TYPE_REACTIONS_LOCK) { iconScale = .8f; paint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); + } else if (type == TYPE_GIFT_LOCK) { + setScaleType(ScaleType.CENTER); + setImageResource(R.drawable.msg_archive_hide); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java index f124c58f20..2f9f50c3bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java @@ -591,7 +591,7 @@ public static void showAboutEnd(boolean isChannel, String from, long msgDate, TL SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); if (isStars) { - stringBuilder.append(replaceTags(formatPluralString(isChannel ? "BoostingStarsGiveawayHowItWorksTextEnd" : "BoostingStarsGiveawayHowItWorksTextEndGroup", (int) giveaway.stars, from))); + stringBuilder.append(replaceTags(formatPluralStringComma(isChannel ? "BoostingStarsGiveawayHowItWorksTextEnd" : "BoostingStarsGiveawayHowItWorksTextEndGroup", (int) giveaway.stars, from))); } else { stringBuilder.append(replaceTags(formatPluralString(isChannel ? "BoostingGiveawayHowItWorksTextEnd" : "BoostingGiveawayHowItWorksTextEndGroup", quantity, from, quantity, months))); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java index b28358e665..727d78a299 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java @@ -1,6 +1,7 @@ package org.telegram.ui.Components.Premium.boosts; import android.os.Build; +import android.text.TextUtils; import android.util.Pair; import com.android.billingclient.api.BillingClient; @@ -103,11 +104,12 @@ public static ArrayList getMyChannels(long currentChatId) { return peers; } - public static void payGiftCode(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + public static void payGiftCode(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, TLRPC.TL_textWithEntities message, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + invalidateGiftOptionsToCache(UserConfig.selectedAccount); if (!isGoogleBillingAvailable()) { - payGiftCodeByInvoice(users, option, chat, baseFragment, onSuccess, onError); + payGiftCodeByInvoice(users, option, chat, message, baseFragment, onSuccess, onError); } else { - payGiftCodeByGoogle(users, option, chat, baseFragment, onSuccess, onError); + payGiftCodeByGoogle(users, option, chat, message, baseFragment, onSuccess, onError); } } @@ -118,7 +120,7 @@ public static boolean isGoogleBillingAvailable() { return BillingController.getInstance().isReady(); } - public static void payGiftCodeByInvoice(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + public static void payGiftCodeByInvoice(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, TLRPC.TL_textWithEntities message, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); @@ -132,9 +134,13 @@ public static void payGiftCodeByInvoice(List users, TLRPC.TL_premiumGi payload.users.add(controller.getInputUser((TLRPC.User) user)); } } + if (message != null && !TextUtils.isEmpty(message.text)) { + payload.flags |= 2; + payload.message = message; + } if (chat != null) { - payload.flags = 1; + payload.flags |= 1; payload.boost_peer = controller.getInputPeer(-chat.id); } @@ -181,7 +187,7 @@ public static void payGiftCodeByInvoice(List users, TLRPC.TL_premiumGi })); } - public static void payGiftCodeByGoogle(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + public static void payGiftCodeByGoogle(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, TLRPC.TL_textWithEntities message, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); TLRPC.TL_inputStorePaymentPremiumGiftCode payload = new TLRPC.TL_inputStorePaymentPremiumGiftCode(); @@ -196,6 +202,10 @@ public static void payGiftCodeByGoogle(List users, TLRPC.TL_premiumGif payload.flags = 1; payload.boost_peer = controller.getInputPeer(-chat.id); } + if (message != null && !TextUtils.isEmpty(message.text)) { + payload.flags |= 2; + payload.message = message; + } QueryProductDetailsParams.Product product = QueryProductDetailsParams.Product.newBuilder() .setProductType(BillingClient.ProductType.INAPP) @@ -551,9 +561,38 @@ public static void loadCountries(Utilities.Callback> onDone) { - MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); - ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + private static HashMap>> cachedGiftOptions; + public static List getCachedGiftOptions(int currentAccount) { + if (cachedGiftOptions == null) return null; + Pair> pair = cachedGiftOptions.get(currentAccount); + if (pair != null && System.currentTimeMillis() - pair.first < 1000 * 60 * 30) { + return pair.second; + } + return null; + } + + public static void saveGiftOptionsToCache(int currentAccount, List options) { + if (cachedGiftOptions == null) cachedGiftOptions = new HashMap<>(); + cachedGiftOptions.put(currentAccount, new Pair<>(System.currentTimeMillis(), options)); + } + + public static void invalidateGiftOptionsToCache(int currentAccount) { + if (cachedGiftOptions != null) { + cachedGiftOptions.remove(currentAccount); + } + } + + public static int loadGiftOptions(int currentAccount, TLRPC.Chat chat, Utilities.Callback> onDone) { + if (chat == null) { + List cached = getCachedGiftOptions(currentAccount); + if (cached != null) { + onDone.run(cached); + return -1; + } + } + + MessagesController controller = MessagesController.getInstance(currentAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(currentAccount); TLRPC.TL_payments_getPremiumGiftCodeOptions req = new TLRPC.TL_payments_getPremiumGiftCodeOptions(); if (chat != null) { req.flags = 1; @@ -576,7 +615,12 @@ public static int loadGiftOptions(TLRPC.Chat chat, Utilities.Callback onDone.run(result)); + AndroidUtilities.runOnUIThread(() -> { + if (chat == null) { + saveGiftOptionsToCache(currentAccount, result); + } + onDone.run(result); + }); return; } BillingController.getInstance().queryProductDetails(products, (billingResult, list) -> { @@ -590,7 +634,12 @@ public static int loadGiftOptions(TLRPC.Chat chat, Utilities.Callback onDone.run(result)); + AndroidUtilities.runOnUIThread(() -> { + if (chat == null) { + saveGiftOptionsToCache(currentAccount, result); + } + onDone.run(result); + }); }); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java index 3f7f38dbc2..c261928cf2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java @@ -1,6 +1,5 @@ package org.telegram.ui.Components.Premium.boosts; -import static org.telegram.messenger.LocaleController.formatPluralString; import static org.telegram.messenger.LocaleController.formatPluralStringComma; import static org.telegram.messenger.LocaleController.getString; @@ -25,6 +24,7 @@ import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -206,7 +206,7 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat } } else if (view instanceof StarGiveawayOptionCell) { StarGiveawayOptionCell cell = (StarGiveawayOptionCell) view; - TLRPC.TL_starsGiveawayOption option = cell.getOption(); + TL_stars.TL_starsGiveawayOption option = cell.getOption(); if (option != null) { selectedStars = option.stars; updateRows(true, true); @@ -282,7 +282,7 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat if (activity == null) activity = LaunchActivity.instance; if (activity == null || activity.isFinishing()) return; - final TLRPC.TL_starsGiveawayOption option = getSelectedStarsOption(); + final TL_stars.TL_starsGiveawayOption option = getSelectedStarsOption(); final int users = getSelectedSliderValue(); if (option == null) return; @@ -341,7 +341,7 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat return; } actionBtn.updateLoading(true); - BoostRepository.payGiftCode(selectedUsers, option, currentChat, fragment, result -> { + BoostRepository.payGiftCode(selectedUsers, option, currentChat, null, fragment, result -> { dismiss(); AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.boostByChannelCreated, currentChat, false), 220); }, error -> { @@ -412,7 +412,7 @@ public void dismiss() { } private void loadOptions() { - BoostRepository.loadGiftOptions(currentChat, arg -> { + BoostRepository.loadGiftOptions(currentAccount, currentChat, arg -> { giftCodeOptions.clear(); giftCodeOptions.addAll(arg); updateRows(true, true); @@ -465,7 +465,7 @@ private int getSelectedSliderValueWithBoosts() { if (selectedBoostType == BoostTypeCell.TYPE_PREMIUM) { return sliderValues.get(selectedSliderIndex) * BoostRepository.giveawayBoostsPerPremium(); } else { - TLRPC.TL_starsGiveawayOption selectedGiveawayOption = getSelectedStarsOption(); + TL_stars.TL_starsGiveawayOption selectedGiveawayOption = getSelectedStarsOption(); return (selectedGiveawayOption != null ? selectedGiveawayOption.yearly_boosts : getSelectedSliderValue() * BoostRepository.giveawayBoostsPerPremium()); } } @@ -486,15 +486,15 @@ private long getSelectedPerUserStars(long stars) { return values.get(Utilities.clamp(selectedStarsSliderIndex, values.size() - 1, 0)); } - public TLRPC.TL_starsGiveawayOption getSelectedStarsOption() { + public TL_stars.TL_starsGiveawayOption getSelectedStarsOption() { return getSelectedStarsOption(selectedStars); } - public TLRPC.TL_starsGiveawayOption getSelectedStarsOption(long stars) { - final ArrayList options = StarsController.getInstance(currentAccount).getGiveawayOptions(); + public TL_stars.TL_starsGiveawayOption getSelectedStarsOption(long stars) { + final ArrayList options = StarsController.getInstance(currentAccount).getGiveawayOptions(); if (options != null) { for (int i = 0; i < options.size(); ++i) { - final TLRPC.TL_starsGiveawayOption option = options.get(i); + final TL_stars.TL_starsGiveawayOption option = options.get(i); if (option != null && option.stars == stars) { return option; } @@ -508,10 +508,10 @@ private List getSliderValues() { return sliderValues; } final ArrayList possibleCounts = new ArrayList<>(); - TLRPC.TL_starsGiveawayOption option = getSelectedStarsOption(); + TL_stars.TL_starsGiveawayOption option = getSelectedStarsOption(); if (option != null) { for (int i = 0; i < option.winners.size(); ++i) { - final TLRPC.TL_starsGiveawayWinnersOption winnersOption = option.winners.get(i); + final TL_stars.TL_starsGiveawayWinnersOption winnersOption = option.winners.get(i); if (option != null && !possibleCounts.contains(winnersOption.users)) { possibleCounts.add(winnersOption.users); } @@ -526,10 +526,10 @@ private List getPerUserStarsValues() { private List getPerUserStarsValues(long selectedStars) { final ArrayList possibleCounts = new ArrayList<>(); final ArrayList stars = new ArrayList<>(); - TLRPC.TL_starsGiveawayOption option = getSelectedStarsOption(selectedStars); + TL_stars.TL_starsGiveawayOption option = getSelectedStarsOption(selectedStars); if (option != null) { for (int i = 0; i < option.winners.size(); ++i) { - final TLRPC.TL_starsGiveawayWinnersOption winnersOption = option.winners.get(i); + final TL_stars.TL_starsGiveawayWinnersOption winnersOption = option.winners.get(i); if (option != null && !possibleCounts.contains(winnersOption.users)) { possibleCounts.add(winnersOption.users); stars.add(winnersOption.per_user_stars); @@ -540,11 +540,11 @@ private List getPerUserStarsValues(long selectedStars) { } private List getStarsOptions() { - final ArrayList options = StarsController.getInstance(currentAccount).getGiveawayOptions(); + final ArrayList options = StarsController.getInstance(currentAccount).getGiveawayOptions(); final ArrayList possibleStars = new ArrayList<>(); if (options != null) { for (int i = 0; i < options.size(); ++i) { - final TLRPC.TL_starsGiveawayOption option = options.get(i); + final TL_stars.TL_starsGiveawayOption option = options.get(i); if (option != null && !possibleStars.contains(option.stars)) { possibleStars.add(option.stars); } @@ -578,7 +578,7 @@ private void updateRows(boolean animated, boolean notify) { int optionsCount = 0; for (int i = 0; i < starOptions.size(); ++i) { final long stars = starOptions.get(i); - TLRPC.TL_starsGiveawayOption option = getSelectedStarsOption(stars); + TL_stars.TL_starsGiveawayOption option = getSelectedStarsOption(stars); if (option.missingStorePrice) continue; if (selectedStars == 0 && option.isDefault) { selectedStars = option.stars; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftSentBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftSentBottomSheet.java index 69f34c6f9f..855bc7bc54 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftSentBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftSentBottomSheet.java @@ -7,13 +7,19 @@ import static org.telegram.messenger.LocaleController.getPluralString; import static org.telegram.messenger.LocaleController.getString; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; import android.graphics.Outline; +import android.graphics.Paint; import android.os.Build; +import android.text.TextPaint; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; +import android.widget.FrameLayout; import android.widget.LinearLayout; import org.telegram.messenger.AndroidUtilities; @@ -23,7 +29,10 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; import org.telegram.ui.Components.Premium.boosts.cells.ActionBtnCell; import org.telegram.ui.LaunchActivity; @@ -112,6 +121,110 @@ public void setTitle(boolean animated) { } } + @SuppressLint("ViewConstructor") + static class AvatarHolderView extends FrameLayout { + + public static View createAvatarsContainer(Context context, List selectedUsers) { + FrameLayout avatarsContainer = new FrameLayout(context); + avatarsContainer.setClipChildren(false); + FrameLayout avatarsWrapper = new FrameLayout(context); + avatarsWrapper.setClipChildren(false); + + if (selectedUsers.size() == 1) { + avatarsContainer.addView(avatarsWrapper, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 94, 0, 0, 0, 0, 0)); + AvatarHolderView avatarHolderView = new AvatarHolderView(context, 47); + avatarHolderView.drawCycle = false; + avatarHolderView.setUser(selectedUsers.get(0)); + avatarsWrapper.addView(avatarHolderView, 0, LayoutHelper.createFrame(94, 94, Gravity.CENTER)); + } else { + avatarsContainer.addView(avatarsWrapper, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 83, 0, 0, 0, 0, 0)); + int visibleCount = 0; + for (int i = 0; i < selectedUsers.size(); i++) { + TLRPC.User user = selectedUsers.get(i); + AvatarHolderView avatarHolderView = new AvatarHolderView(context, 41.5f); + avatarHolderView.setUser(user); + avatarsWrapper.addView(avatarHolderView, 0, LayoutHelper.createFrame(83, 83, Gravity.CENTER)); + avatarHolderView.setTranslationX(-i * dp(29)); + if (i == 0 && selectedUsers.size() > 3) { + avatarHolderView.iconView.setAlpha(1f); + avatarHolderView.iconView.count = selectedUsers.size() - 3; + } + visibleCount++; + if (i == 2) { + break; + } + } + avatarsContainer.setTranslationX(dp(29 / 2f) * (visibleCount - 1)); + } + return avatarsContainer; + } + + private final BackupImageView imageView; + protected final AdditionalCounterView iconView; + private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + public TLRPC.User user; + public boolean drawCycle = true; + AvatarDrawable fromAvatarDrawable = new AvatarDrawable(); + + public AvatarHolderView(Context context, float radiusDp) { + super(context); + imageView = new BackupImageView(getContext()); + imageView.setRoundRadius(AndroidUtilities.dp(radiusDp)); + iconView = new AdditionalCounterView(context); + iconView.setAlpha(0f); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 5, 5, 5, 5)); + addView(iconView, LayoutHelper.createFrame(26, 26, Gravity.BOTTOM | Gravity.RIGHT, 0, 0, 1, 3)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + bgPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); + } else { + bgPaint.setColor(Theme.getColor(Theme.key_dialogBackground)); + } + } + + public void setUser(TLRPC.User user) { + this.user = user; + fromAvatarDrawable.setInfo(user); + imageView.setForUserOrChat(user, fromAvatarDrawable); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (drawCycle) { + canvas.drawCircle(getMeasuredWidth() / 2f, getMeasuredHeight() / 2f, (getMeasuredHeight() / 2f) - dp(2f), bgPaint); + } + super.dispatchDraw(canvas); + } + } + + static class AdditionalCounterView extends View { + + TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + int count; + + public AdditionalCounterView(Context context) { + super(context); + paint.setTextAlign(Paint.Align.CENTER); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + paint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); + } else { + paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + } + paint.setTextSize(dp(11.5f)); + paint.setTypeface(AndroidUtilities.bold()); + } + + @Override + protected void onDraw(Canvas canvas) { + float cx = getMeasuredWidth() / 2f; + float cy = getMeasuredHeight() / 2f; + canvas.drawCircle(cx, cy, getMeasuredWidth() / 2f, paint); + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -AndroidUtilities.dp(10), 0); + canvas.drawCircle(cx, cy, getMeasuredWidth() / 2f - AndroidUtilities.dp(1.5f), PremiumGradient.getInstance().getMainGradientPaint()); + cy = (int) (cy - ((paint.descent() + paint.ascent()) / 2f)); + canvas.drawText("+" + count, cx, cy, paint); + } + } + private void init() { updateRows(); useBackgroundTopPadding = false; @@ -123,7 +236,7 @@ private void init() { containerView.addView(actionBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, BOTTOM_HEIGHT_DP, Gravity.BOTTOM, 0, 0, 0, 0)); recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(BOTTOM_HEIGHT_DP)); - overrideTitleIcon = PremiumPreviewGiftToUsersBottomSheet.AvatarHolderView.createAvatarsContainer(getContext(), selectedUsers); + overrideTitleIcon = AvatarHolderView.createAvatarsContainer(getContext(), selectedUsers); fixNavigationBar(); } 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 deleted file mode 100644 index 7a6d8b3e29..0000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java +++ /dev/null @@ -1,414 +0,0 @@ -package org.telegram.ui.Components.Premium.boosts; - -import static org.telegram.messenger.AndroidUtilities.dp; -import static org.telegram.messenger.AndroidUtilities.replaceTags; -import static org.telegram.messenger.LocaleController.formatPluralString; -import static org.telegram.messenger.LocaleController.formatString; -import static org.telegram.messenger.LocaleController.getString; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Outline; -import android.graphics.Paint; -import android.os.Build; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.TextPaint; -import android.text.TextUtils; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewOutlineProvider; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.BillingController; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; -import org.telegram.messenger.UserConfig; -import org.telegram.messenger.UserObject; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Cells.HeaderCell; -import org.telegram.ui.Cells.ShadowSectionCell; -import org.telegram.ui.Components.AvatarDrawable; -import org.telegram.ui.Components.BackupImageView; -import org.telegram.ui.Components.ColoredImageSpan; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.Premium.PremiumGradient; -import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; -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; -import java.util.Comparator; -import java.util.List; - -public class PremiumPreviewGiftToUsersBottomSheet extends PremiumPreviewBottomSheet { - private static final int BOTTOM_HEIGHT_DP = 64; - private static final int CELL_TYPE_HEADER = 6, - CELL_TYPE_SHADOW = 7, - CELL_TYPE_DURATION = 8; - - private GradientButtonWithCounterView actionBtn; - private SelectorBtnCell buttonContainer; - private final List selectedUsers = new ArrayList<>(); - private final List giftCodeOptions = new ArrayList<>(); - private int selectedMonths = 3; - - public static void show(List selectedUsers, List giftCodeOptions) { - BaseFragment fragment = LaunchActivity.getLastFragment(); - if (fragment == null) { - return; - } - PremiumPreviewGiftToUsersBottomSheet sheet = new PremiumPreviewGiftToUsersBottomSheet(fragment, UserConfig.selectedAccount, selectedUsers, giftCodeOptions, fragment.getResourceProvider()); - fragment.showDialog(sheet); - } - - public PremiumPreviewGiftToUsersBottomSheet(BaseFragment fragment, int currentAccount, List selectedUsers, List giftCodeOptions, Theme.ResourcesProvider resourcesProvider) { - super(fragment, currentAccount, null, null, resourcesProvider); - this.selectedUsers.addAll(selectedUsers); - this.giftCodeOptions.addAll(giftCodeOptions); - Collections.sort(giftCodeOptions, Comparator.comparingLong(o -> o.amount)); - init(); - } - - @Override - protected boolean needDefaultPremiumBtn() { - return false; - } - - @Override - protected void updateRows() { - rowCount = 0; - paddingRow = rowCount++; - additionStartRow = rowCount; - rowCount += (giftCodeOptions != null ? giftCodeOptions.size() : 0) + 2; - additionEndRow = rowCount; - featuresStartRow = rowCount; - rowCount += premiumFeatures.size(); - featuresEndRow = rowCount; - termsRow = rowCount++; - } - - @Override - public void setTitle(boolean animated) { - titleView[0].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - ((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: { - String names = formatString("GiftPremiumUsersOne", R.string.GiftPremiumUsersOne, UserObject.getFirstName(selectedUsers.get(0))); - subTitle = formatString("GiftPremiumUsersGiveAccessManyZero", R.string.GiftPremiumUsersGiveAccessManyZero, names); - break; - } - case 2: { - String names = formatString("GiftPremiumUsersTwo", R.string.GiftPremiumUsersTwo, UserObject.getFirstName(selectedUsers.get(0)), UserObject.getFirstName(selectedUsers.get(1))); - subTitle = formatString("GiftPremiumUsersGiveAccessManyZero", R.string.GiftPremiumUsersGiveAccessManyZero, names); - break; - } - case 3: { - String names = formatString("GiftPremiumUsersThree", R.string.GiftPremiumUsersThree, UserObject.getFirstName(selectedUsers.get(0)), UserObject.getFirstName(selectedUsers.get(1)), UserObject.getFirstName(selectedUsers.get(2))); - subTitle = formatString("GiftPremiumUsersGiveAccessManyZero", R.string.GiftPremiumUsersGiveAccessManyZero, names); - break; - } - default: { - String names = formatString("GiftPremiumUsersThree", R.string.GiftPremiumUsersThree, UserObject.getFirstName(selectedUsers.get(0)), UserObject.getFirstName(selectedUsers.get(1)), UserObject.getFirstName(selectedUsers.get(2))); - subTitle = formatPluralString("GiftPremiumUsersGiveAccessMany", selectedUsers.size() - 3, names); - break; - } - } - subtitleView.setText(replaceTags(subTitle)); - - subtitleView.append("\n"); - subtitleView.append("\n"); - CharSequence boostInfo = replaceTags(formatPluralString("GiftPremiumWillReceiveBoostsPlural", selectedUsers.size() * BoostRepository.boostsPerSentGift())); - SpannableStringBuilder boostInfoSpannableBuilder = new SpannableStringBuilder(boostInfo); - ColoredImageSpan span = new ColoredImageSpan(R.drawable.mini_boost_button); - span.setSize(dp(20)); - span.setWidth(dp(11)); - span.setTranslateX(-dp(4)); - span.setTranslateY(-dp(1)); - span.setColorKey(Theme.key_windowBackgroundWhiteBlueText4); - String lightning = "⚡"; - int lightningIndex = TextUtils.indexOf(boostInfo, lightning); - if (lightningIndex >= 0) { - boostInfoSpannableBuilder.setSpan(span, lightningIndex, lightningIndex + lightning.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - subtitleView.append(boostInfoSpannableBuilder); - } - - @Override - protected View onCreateAdditionCell(int viewType, Context context) { - switch (viewType) { - case CELL_TYPE_HEADER: { - HeaderCell cell = new HeaderCell(context,Theme.key_windowBackgroundWhiteBlueHeader, 21, 12, false, resourcesProvider); - cell.setTextSize(15); - cell.setPadding(0, 0, 0, dp(2)); - cell.setText(getString("GiftPremiumWhatsIncluded", R.string.GiftPremiumWhatsIncluded)); - return cell; - } - case CELL_TYPE_SHADOW: { - return new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); - } - case CELL_TYPE_DURATION: { - return new DurationWithDiscountCell(context, resourcesProvider); - } - default: - return null; - } - } - - @Override - protected void onAdditionItemClicked(View view) { - if (view instanceof DurationWithDiscountCell) { - DurationWithDiscountCell cell = ((DurationWithDiscountCell) view); - selectedMonths = cell.getOption().months; - cell.markChecked(recyclerListView); - updateActionButton(true); - } - } - - @Override - protected boolean isAdditionViewClickable(int viewType) { - return viewType == 8; - } - - @Override - protected void onBindAdditionCell(View view, int pos) { - if (view instanceof DurationWithDiscountCell) { - pos = pos - 1; - TLRPC.TL_premiumGiftCodeOption option = giftCodeOptions.get(pos); - ((DurationWithDiscountCell) view).setDuration(option, giftCodeOptions.get(giftCodeOptions.size() - 1), selectedUsers.size(), pos != giftCodeOptions.size() - 1, selectedMonths == option.months); - } - } - - @Override - protected int getAdditionItemViewType(int position) { - if (position <= giftCodeOptions.size()) { - return CELL_TYPE_DURATION; - } else if (position == giftCodeOptions.size() + 1) { - return CELL_TYPE_SHADOW; - } else if (position == giftCodeOptions.size() + 2) { - return CELL_TYPE_HEADER; - } - return 0; - } - - private TLRPC.TL_premiumGiftCodeOption getSelectedOption() { - for (TLRPC.TL_premiumGiftCodeOption giftCodeOption : giftCodeOptions) { - if (giftCodeOption.months == selectedMonths) { - return giftCodeOption; - } - } - return giftCodeOptions.get(0); - } - - private void updateActionButton(boolean animated) { - TLRPC.TL_premiumGiftCodeOption giftCodeOption = getSelectedOption(); - String priceStr = BillingController.getInstance().formatCurrency(giftCodeOption.amount, giftCodeOption.currency); - if (selectedUsers.size() == 1) { - actionBtn.setText(formatString(R.string.GiftSubscriptionFor, priceStr), animated); - } else { - actionBtn.setText(formatPluralString("GiftSubscriptionCountFor", selectedUsers.size(), priceStr), animated); - } - } - - private void chooseMaxSelectedMonths() { - for (TLRPC.TL_premiumGiftCodeOption giftCodeOption : giftCodeOptions) { - selectedMonths = Math.max(giftCodeOption.months, selectedMonths); - } - } - - private void init() { - chooseMaxSelectedMonths(); - updateRows(); - useBackgroundTopPadding = false; - setApplyTopPadding(false); - backgroundPaddingTop = 0; - recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(BOTTOM_HEIGHT_DP)); - - buttonContainer = new SelectorBtnCell(getContext(), resourcesProvider, recyclerListView); - buttonContainer.setClickable(true); - buttonContainer.setOrientation(LinearLayout.VERTICAL); - buttonContainer.setPadding(dp(8), dp(8), dp(8), dp(8)); - buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); - actionBtn = new GradientButtonWithCounterView(getContext(), true, resourcesProvider); - actionBtn.setOnClickListener(v -> { - if (actionBtn.isLoading()) { - return; - } - actionBtn.setLoading(true); - 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)); - - 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) { - view.setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - float cornerRadius = AndroidUtilities.dp(12); - outline.setRoundRect(0, 0, view.getWidth(), (int) (view.getHeight() + cornerRadius), cornerRadius); - } - }); - view.setClipToOutline(true); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); - } - ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = -dp(6); - } - } - - @Override - protected void attachIconContainer(LinearLayout container) { - container.addView(overrideTitleIcon, LayoutHelper.createLinear( - LayoutHelper.MATCH_PARENT, - selectedUsers.size() == 1 ? 94 : 83, - 0, - selectedUsers.size() == 1 ? 28 : 34, - 0, - selectedUsers.size() == 1 ? 9 : 14) - ); - } - - @SuppressLint("ViewConstructor") - static class AvatarHolderView extends FrameLayout { - - public static View createAvatarsContainer(Context context, List selectedUsers) { - FrameLayout avatarsContainer = new FrameLayout(context); - avatarsContainer.setClipChildren(false); - FrameLayout avatarsWrapper = new FrameLayout(context); - avatarsWrapper.setClipChildren(false); - - if (selectedUsers.size() == 1) { - avatarsContainer.addView(avatarsWrapper, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 94, 0, 0, 0, 0, 0)); - PremiumPreviewGiftToUsersBottomSheet.AvatarHolderView avatarHolderView = new PremiumPreviewGiftToUsersBottomSheet.AvatarHolderView(context, 47); - avatarHolderView.drawCycle = false; - avatarHolderView.setUser(selectedUsers.get(0)); - avatarsWrapper.addView(avatarHolderView, 0, LayoutHelper.createFrame(94, 94, Gravity.CENTER)); - } else { - avatarsContainer.addView(avatarsWrapper, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 83, 0, 0, 0, 0, 0)); - int visibleCount = 0; - for (int i = 0; i < selectedUsers.size(); i++) { - TLRPC.User user = selectedUsers.get(i); - PremiumPreviewGiftToUsersBottomSheet.AvatarHolderView avatarHolderView = new PremiumPreviewGiftToUsersBottomSheet.AvatarHolderView(context, 41.5f); - avatarHolderView.setUser(user); - avatarsWrapper.addView(avatarHolderView, 0, LayoutHelper.createFrame(83, 83, Gravity.CENTER)); - avatarHolderView.setTranslationX(-i * dp(29)); - if (i == 0 && selectedUsers.size() > 3) { - avatarHolderView.iconView.setAlpha(1f); - avatarHolderView.iconView.count = selectedUsers.size() - 3; - } - visibleCount++; - if (i == 2) { - break; - } - } - avatarsContainer.setTranslationX(dp(29 / 2f) * (visibleCount - 1)); - } - return avatarsContainer; - } - - private final BackupImageView imageView; - protected final AdditionalCounterView iconView; - private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - public TLRPC.User user; - public boolean drawCycle = true; - AvatarDrawable fromAvatarDrawable = new AvatarDrawable(); - - public AvatarHolderView(Context context, float radiusDp) { - super(context); - imageView = new BackupImageView(getContext()); - imageView.setRoundRadius(AndroidUtilities.dp(radiusDp)); - iconView = new AdditionalCounterView(context); - iconView.setAlpha(0f); - addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 5, 5, 5, 5)); - addView(iconView, LayoutHelper.createFrame(26, 26, Gravity.BOTTOM | Gravity.RIGHT, 0, 0, 1, 3)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - bgPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); - } else { - bgPaint.setColor(Theme.getColor(Theme.key_dialogBackground)); - } - } - - public void setUser(TLRPC.User user) { - this.user = user; - fromAvatarDrawable.setInfo(user); - imageView.setForUserOrChat(user, fromAvatarDrawable); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - if (drawCycle) { - canvas.drawCircle(getMeasuredWidth() / 2f, getMeasuredHeight() / 2f, (getMeasuredHeight() / 2f) - dp(2f), bgPaint); - } - super.dispatchDraw(canvas); - } - } - - static class AdditionalCounterView extends View { - - TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - int count; - - public AdditionalCounterView(Context context) { - super(context); - paint.setTextAlign(Paint.Align.CENTER); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - paint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); - } else { - paint.setColor(Theme.getColor(Theme.key_dialogBackground)); - } - paint.setTextSize(dp(11.5f)); - paint.setTypeface(AndroidUtilities.bold()); - } - - @Override - protected void onDraw(Canvas canvas) { - float cx = getMeasuredWidth() / 2f; - float cy = getMeasuredHeight() / 2f; - canvas.drawCircle(cx, cy, getMeasuredWidth() / 2f, paint); - PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -AndroidUtilities.dp(10), 0); - canvas.drawCircle(cx, cy, getMeasuredWidth() / 2f - AndroidUtilities.dp(1.5f), PremiumGradient.getInstance().getMainGradientPaint()); - cy = (int) (cy - ((paint.descent() + paint.ascent()) / 2f)); - canvas.drawText("+" + count, cx, cy, paint); - } - } -} 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 316d32515a..5255fce3de 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 @@ -1,9 +1,7 @@ package org.telegram.ui.Components.Premium.boosts; -import static org.telegram.messenger.AndroidUtilities.checkAndroidTheme; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.LocaleController.getString; -import static org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter.VIEW_TYPE_TOP_SECTION; import android.annotation.SuppressLint; import android.content.Intent; @@ -45,7 +43,6 @@ 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; @@ -63,10 +60,11 @@ 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.Gifts.GiftSheet; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PrivacyControlActivity; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stars.StarsController; import org.telegram.ui.Stars.StarsIntroActivity; import org.telegram.ui.Stories.recorder.ButtonWithCounterView; @@ -83,6 +81,7 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp public static final int TYPE_PREMIUM = 0; public static final int TYPE_STARS = 1; + public static final int TYPE_STAR_GIFT = 2; private static UserSelectorBottomSheet instance; @@ -197,7 +196,7 @@ private void loadData(String query) { } private void checkEditTextHint() { - if (!selectedIds.isEmpty() || type == TYPE_STARS) { + if (!selectedIds.isEmpty() || type == TYPE_STARS || type == TYPE_STAR_GIFT) { if (!isHintSearchText) { isHintSearchText = true; AndroidUtilities.runOnUIThread(() -> searchField.setHintText(getString(R.string.Search), true), 10); @@ -229,12 +228,12 @@ public UserSelectorBottomSheet(BaseFragment fragment, long userId, BirthdayContr this.type = type; this.birthdays = state; - if (birthdays != null && !birthdays.today.isEmpty() && type == TYPE_PREMIUM) { - for (TLRPC.User user : birthdays.today) { - selectedIds.add(user.id); - allSelectedObjects.put(user.id, user); - } - } +// if (birthdays != null && !birthdays.today.isEmpty() && type == TYPE_PREMIUM) { +// for (TLRPC.User user : birthdays.today) { +// selectedIds.add(user.id); +// allSelectedObjects.put(user.id, user); +// } +// } this.userId = userId; if (userId != 0 && fragment != null && !selectedIds.contains(userId)) { TLRPC.User user = fragment.getMessagesController().getUser(userId); @@ -277,7 +276,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { }; searchField.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); searchField.setOnSearchTextChange(this::onSearch); - searchField.setHintText(getString(!selectedIds.isEmpty() || type == TYPE_STARS ? R.string.Search : R.string.GiftPremiumUsersSearchHint), false); + searchField.setHintText(getString(!selectedIds.isEmpty() || type == TYPE_STARS || type == TYPE_STAR_GIFT ? R.string.Search : R.string.GiftPremiumUsersSearchHint), false); sectionCell = new View(getContext()) { @Override @@ -309,9 +308,7 @@ protected float calculateCounterWidth(float width, float percent) { }; actionButton.setOnClickListener(v -> next()); buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); - if (type != TYPE_STARS) { - containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); - } +// 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))); @@ -333,6 +330,7 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat } if (view instanceof SelectorUserCell) { TLRPC.User user = ((SelectorUserCell) view).getUser(); + long id = user.id; if (type == TYPE_STARS) { if (searchField != null) { AndroidUtilities.hideKeyboard(searchField.getEditText()); @@ -344,7 +342,12 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat sheet.show(); return; } - long id = user.id; + if (type == TYPE_PREMIUM || type == TYPE_STAR_GIFT) { + List options = BoostRepository.filterGiftOptions(paymentOptions, 1); + options = BoostRepository.filterGiftOptionsByBilling(options); + new GiftSheet(getContext(), currentAccount, id, options, this::dismiss).show(); + return; + } if (selectedIds.contains(id)) { selectedIds.remove(id); } else { @@ -394,12 +397,21 @@ public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull R initHints(false); updateList(false, true); fixNavigationBar(); - if (type == TYPE_PREMIUM) { - BoostRepository.loadGiftOptions(null, arg -> { + if (type == TYPE_PREMIUM || type == TYPE_STAR_GIFT) { + BoostRepository.loadGiftOptions(currentAccount, null, arg -> { paymentOptions.clear(); paymentOptions.addAll(arg); + if (actionButton.isLoading()) { + actionButton.setLoading(false); + if (recyclerListView.isAttachedToWindow()) { + next(); + } + } }); } + if (type == TYPE_PREMIUM || type == TYPE_STAR_GIFT) { + StarsController.getInstance(currentAccount).loadStarGifts(); + } } private void initContacts(boolean needUpdate) { @@ -433,7 +445,7 @@ protected void onPreDraw(Canvas canvas, int top, float progressToFullView) { } private void next() { - if (selectedIds.size() == 0 || paymentOptions.isEmpty()) { + if (selectedIds.size() == 0 || paymentOptions.isEmpty() && (type != TYPE_PREMIUM && type != TYPE_STAR_GIFT)) { return; } List selectedUsers = new ArrayList<>(); @@ -444,12 +456,15 @@ private void next() { } AndroidUtilities.hideKeyboard(searchField.getEditText()); if (type == TYPE_STARS) { - - } else { - List options = BoostRepository.filterGiftOptions(paymentOptions, selectedUsers.size()); - options = BoostRepository.filterGiftOptionsByBilling(options); - PremiumPreviewGiftToUsersBottomSheet.show(selectedUsers, options); + return; + } + List options = BoostRepository.filterGiftOptions(paymentOptions, selectedUsers.size()); + options = BoostRepository.filterGiftOptionsByBilling(options); + if (selectedUsers.size() == 1) { + new GiftSheet(getContext(), currentAccount, selectedUsers.get(0).id, options, this::dismiss).show(); + return; } +// PremiumPreviewGiftToUsersBottomSheet.show(selectedUsers, options); } public void scrollToTop(boolean animate) { @@ -778,12 +793,15 @@ protected CharSequence getTitle() { if (getType() == TYPE_STARS) { return getString(R.string.GiftStarsTitle); } + if ((getType() == TYPE_STAR_GIFT || getType() == TYPE_PREMIUM) && !MessagesController.getInstance(currentAccount).stargiftsBlocked) { + return getString(R.string.GiftTelegramPremiumOrStarsTitle); + } return getString(R.string.GiftTelegramPremiumTitle); } @Override protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { - selectorAdapter = new SelectorAdapter(getContext(), getType() != TYPE_STARS, resourcesProvider); + selectorAdapter = new SelectorAdapter(getContext(), false, resourcesProvider); selectorAdapter.setGreenSelector(true); return selectorAdapter; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/BoostAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/BoostAdapter.java index e77c70dcdf..f0bb84e3d6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/BoostAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/BoostAdapter.java @@ -1,13 +1,11 @@ package org.telegram.ui.Components.Premium.boosts.adapters; -import android.annotation.SuppressLint; import android.content.Context; 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.telegram.messenger.LocaleController; @@ -16,6 +14,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ShadowSectionCell; @@ -366,7 +365,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } case HOLDER_TYPE_STAR_OPTION: { StarGiveawayOptionCell cell = (StarGiveawayOptionCell) holder.itemView; - cell.setOption(item.object == null ? null : (TLRPC.TL_starsGiveawayOption) item.object, item.intValue, item.longValue, item.selectable, item.boolValue); + cell.setOption(item.object == null ? null : (TL_stars.TL_starsGiveawayOption) item.object, item.intValue, item.longValue, item.selectable, item.boolValue); break; } case HOLDER_TYPE_SIMPLE_DIVIDER: { @@ -527,7 +526,7 @@ public static Item asDuration(Object code, int months, int count, long price, in return item; } - public static Item asOption(TLRPC.TL_starsGiveawayOption option, int index, long starsPerUser, boolean selected, boolean needDivider) { + public static Item asOption(TL_stars.TL_starsGiveawayOption option, int index, long starsPerUser, boolean selected, boolean needDivider) { Item item = new Item(HOLDER_TYPE_STAR_OPTION, selected); item.intValue = index; item.longValue = starsPerUser; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/StarGiveawayOptionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/StarGiveawayOptionCell.java index 3ea16e9a2b..887ef2db2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/StarGiveawayOptionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/StarGiveawayOptionCell.java @@ -21,7 +21,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; -import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; @@ -82,10 +82,10 @@ public StarGiveawayOptionCell(Context context, Theme.ResourcesProvider resources addView(radioButton, LayoutHelper.createFrame(20, 20, Gravity.LEFT | Gravity.CENTER_VERTICAL, 22, 0, 0, 0)); } - private TLRPC.TL_starsGiveawayOption currentOption; + private TL_stars.TL_starsGiveawayOption currentOption; private long currentOptionStarsPerUser; - public void setOption(TLRPC.TL_starsGiveawayOption option, int index, long per_user_stars, boolean selected, boolean needDivider) { + public void setOption(TL_stars.TL_starsGiveawayOption option, int index, long per_user_stars, boolean selected, boolean needDivider) { final boolean animated = currentOption == option; radioButton.setChecked(selected, animated); @@ -114,7 +114,7 @@ public void setOption(TLRPC.TL_starsGiveawayOption option, int index, long per_u } - public TLRPC.TL_starsGiveawayOption getOption() { + public TL_stars.TL_starsGiveawayOption getOption() { return currentOption; } 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 0f5f6d6f01..c486e9b99e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java @@ -142,18 +142,17 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b thumbLocation = ImageLocation.getForPath(document.localThumbPath); thumbFilter = w + "_" + h; } + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (onlyLastFrame) { - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + "_lastframe", null, null, thumbLocation, thumbFilter, null, 0, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + "_lastframe", ImageLocation.getForDocument(thumb, document), w + "_" + h, 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, 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, thumbLocation, thumbFilter, svgThumb, 0, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : ""), ImageLocation.getForDocument(thumb, document), w + "_" + h, thumbLocation, thumbFilter, svgThumb, 0, null, document, 1); } imageReceiver.setAspectFit(true); imageReceiver.setParentView(this); 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 d658d14307..ef394f2ea1 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 @@ -205,7 +205,7 @@ protected void onReactionClick(ImageViewEmoji emoji, ReactionsLayoutInBubble.Vis @Override protected void onEmojiSelected(View emojiView, Long documentId, TLRPC.Document document, Integer until) { - if (baseFragment != null && reactionsContainerLayout.getWindowType() != SelectAnimatedEmojiDialog.TYPE_STICKER_SET_EMOJI && !UserConfig.getInstance(baseFragment.getCurrentAccount()).isPremium()) { + if (baseFragment != null && !reactionsContainerLayout.channelReactions && reactionsContainerLayout.getWindowType() != SelectAnimatedEmojiDialog.TYPE_STICKER_SET_EMOJI && !UserConfig.getInstance(baseFragment.getCurrentAccount()).isPremium()) { windowView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); BulletinFactory.of(windowView, null).createEmojiBulletin( document, 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 97327e35cc..6433baa099 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -210,6 +210,8 @@ public boolean equals(Object o) { public ReactionHolderView nextRecentReaction; + public boolean channelReactions; + float pullingLeftOffset; HashSet lastVisibleViews = new HashSet<>(); @@ -1044,6 +1046,7 @@ public void setMessage(MessageObject message, TLRPC.ChatFull chatFull, boolean a } } hitLimit = type == TYPE_DEFAULT && messageObject != null && chosenCount >= MessagesController.getInstance(currentAccount).getChatMaxUniqReactions(messageObject.getDialogId()); + channelReactions = type == TYPE_DEFAULT && messageObject != null && ChatObject.isChannelAndNotMegaGroup(MessagesController.getInstance(currentAccount).getChat(-messageObject.getDialogId())); TLRPC.ChatFull reactionsChat = chatFull; List visibleReactions = new ArrayList<>(); if (message != null && message.isForwardedChannelPost()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java deleted file mode 100644 index c9ad2bdd87..0000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 5.x.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2018. - */ - -package org.telegram.ui.Components; - -import android.content.Context; -import android.text.InputType; -import android.text.TextUtils; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.R; -import org.telegram.ui.ActionBar.BottomSheet; -import org.telegram.ui.ActionBar.Theme; - -public class ReportAlert extends BottomSheet { - - private BottomSheetCell clearButton; - private EditTextBoldCursor editText; - - public static class BottomSheetCell extends FrameLayout { - - private View background; - private TextView textView; - private LinearLayout linearLayout; - - public BottomSheetCell(Context context, Theme.ResourcesProvider resourcesProvider) { - super(context); - - background = new View(context); - background.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 4)); - addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16)); - - textView = new TextView(context); - textView.setLines(1); - textView.setSingleLine(true); - textView.setGravity(Gravity.CENTER_HORIZONTAL); - textView.setEllipsize(TextUtils.TruncateAt.END); - textView.setGravity(Gravity.CENTER); - textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView.setTypeface(AndroidUtilities.bold()); - addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY)); - } - - public void setText(CharSequence text) { - textView.setText(text); - } - } - - public ReportAlert(final Context context, int type, Theme.ResourcesProvider resourcesProvider) { - super(context, true, resourcesProvider); - setApplyBottomPadding(false); - setApplyTopPadding(false); - - ScrollView scrollView = new ScrollView(context); - scrollView.setFillViewport(true); - setCustomView(scrollView); - - FrameLayout frameLayout = new FrameLayout(context); - scrollView.addView(frameLayout, LayoutHelper.createScroll(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); - - RLottieImageView imageView = new RLottieImageView(context); - imageView.setAnimation(R.raw.report_police, 120, 120); - imageView.playAnimation(); - frameLayout.addView(imageView, LayoutHelper.createFrame(160, 160, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 17, 14, 17, 0)); - - TextView percentTextView = new TextView(context); - percentTextView.setTypeface(AndroidUtilities.bold()); - percentTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24); - percentTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); - if (type == AlertsCreator.REPORT_TYPE_SPAM) { - percentTextView.setText(LocaleController.getString(R.string.ReportTitleSpam)); - } else if (type == AlertsCreator.REPORT_TYPE_FAKE_ACCOUNT) { - percentTextView.setText(LocaleController.getString(R.string.ReportTitleFake)); - } else if (type == AlertsCreator.REPORT_TYPE_VIOLENCE) { - percentTextView.setText(LocaleController.getString(R.string.ReportTitleViolence)); - } else if (type == AlertsCreator.REPORT_TYPE_CHILD_ABUSE) { - percentTextView.setText(LocaleController.getString(R.string.ReportTitleChild)); - } else if (type == AlertsCreator.REPORT_TYPE_PORNOGRAPHY) { - percentTextView.setText(LocaleController.getString(R.string.ReportTitlePornography)); - } else if (type == AlertsCreator.REPORT_TYPE_OTHER) { - percentTextView.setText(LocaleController.getString(R.string.ReportChat)); - } - frameLayout.addView(percentTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 17, 197, 17, 0)); - - TextView infoTextView = new TextView(context); - infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - infoTextView.setTextColor(getThemedColor(Theme.key_dialogTextGray3)); - infoTextView.setGravity(Gravity.CENTER_HORIZONTAL); - infoTextView.setText(LocaleController.getString(R.string.ReportInfo)); - frameLayout.addView(infoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 30, 235, 30, 44)); - - editText = new EditTextBoldCursor(context); - editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - editText.setHintTextColor(getThemedColor(Theme.key_windowBackgroundWhiteHintText)); - editText.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); - editText.setBackgroundDrawable(null); - editText.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_text_RedRegular)); - editText.setMaxLines(1); - editText.setLines(1); - editText.setPadding(0, 0, 0, 0); - editText.setSingleLine(true); - editText.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); - editText.setImeOptions(EditorInfo.IME_ACTION_DONE); - editText.setHint(LocaleController.getString(R.string.ReportHint)); - editText.setCursorColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); - editText.setCursorSize(AndroidUtilities.dp(20)); - editText.setCursorWidth(1.5f); - editText.setOnEditorActionListener((textView, i, keyEvent) -> { - if (i == EditorInfo.IME_ACTION_DONE) { - clearButton.background.callOnClick(); - return true; - } - return false; - }); - frameLayout.addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 17, 305, 17, 0)); - - clearButton = new BottomSheetCell(context, resourcesProvider); - clearButton.setBackground(null); - clearButton.setText(LocaleController.getString(R.string.ReportSend)); - clearButton.background.setOnClickListener(v -> { - AndroidUtilities.hideKeyboard(editText); - onSend(type, editText.getText().toString()); - dismiss(); - }); - frameLayout.addView(clearButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.LEFT | Gravity.TOP, 0, 357, 0, 0)); - smoothKeyboardAnimationEnabled = true; - } - - protected void onSend(int type, String message) { - - } -} 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 71f631ffd7..bac2b03822 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java @@ -35,6 +35,8 @@ import androidx.annotation.Keep; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.NotificationCenter; import org.telegram.ui.ActionBar.Theme; public class ScrollSlidingTextTabStrip extends HorizontalScrollView { @@ -288,7 +290,7 @@ public void addTextTab(final int id, CharSequence text, SparseArray viewsC viewsCache.delete(id); } if (tab == null) { - tab = new TextView(getContext()) { + tab = new AnimatedEmojiSpan.TextViewEmojis(getContext()) { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); @@ -306,7 +308,9 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { int position1 = tabsContainer.indexOfChild(v); scrollTo(id, position1, v); }); + NotificationCenter.listenEmojiLoading(tab); } + text = Emoji.replaceEmoji(text, tab.getPaint().getFontMetricsInt(), false); tab.setText(text); int tabWidth = (int) Math.ceil(tab.getPaint().measureText(text, 0, text.length())) + tab.getPaddingLeft() + tab.getPaddingRight(); tabsContainer.addView(tab, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT)); 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 85909a58b4..c42de0af09 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java @@ -452,6 +452,12 @@ public void updateTabs() { } private void search(View view, int position, String query, boolean reset) { + if (TextUtils.isEmpty(query)) { + emptyView.subtitle.setVisibility(View.GONE); + } else { + emptyView.subtitle.setVisibility(View.VISIBLE); + emptyView.subtitle.setText(LocaleController.formatString(R.string.NoResultFoundFor2, query)); + } long forumDialogId = dialogsSearchAdapter.delegate != null ? dialogsSearchAdapter.delegate.getSearchForumDialogId() : 0; long dialogId = position == 0 ? 0 : forumDialogId; long minDate = 0; 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 63400619da..20be47b037 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -128,6 +128,7 @@ import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; +import org.telegram.ui.Gifts.ProfileGiftsContainer; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; @@ -164,6 +165,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public static final int TAB_SAVED_DIALOGS = 11; public static final int TAB_SAVED_MESSAGES = 12; public static final int TAB_BOT_PREVIEWS = 13; + public static final int TAB_GIFTS = 14; public static final int FILTER_PHOTOS_AND_VIDEOS = 0; public static final int FILTER_PHOTOS_ONLY = 1; @@ -613,6 +615,7 @@ public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { private SavedMessagesSearchAdapter savedMessagesSearchAdapter; private ChatActivityContainer savedMessagesContainer; private BotPreviewsEditContainer botPreviewsContainer; + public ProfileGiftsContainer giftsContainer; private ChatUsersAdapter chatUsersAdapter; private ItemTouchHelper storiesReorder; private StoriesAdapter storiesAdapter; @@ -1458,7 +1461,9 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload int[] mediaCount = preloader.getLastMediaCount(); topicId = sharedMediaPreloader.topicId; hasMedia = new int[]{mediaCount[0], mediaCount[1], mediaCount[2], mediaCount[3], mediaCount[4], mediaCount[5], topicId == 0 ? commonGroupsCount : 0}; - if (initialTab == TAB_RECOMMENDED_CHANNELS) { + if (initialTab == TAB_GIFTS) { + this.initialTab = initialTab; + } else if (initialTab == TAB_RECOMMENDED_CHANNELS) { this.initialTab = initialTab; } else if (initialTab == TAB_SAVED_DIALOGS) { this.initialTab = initialTab; @@ -1468,6 +1473,8 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload this.initialTab = TAB_STORIES; } else if (userInfo != null && userInfo.stories_pinned_available || chatInfo != null && chatInfo.stories_pinned_available || isStoriesView()) { this.initialTab = getInitialTab(); + } else if (userInfo != null && userInfo.stargifts_count > 0) { + this.initialTab = TAB_GIFTS; } else if (initialTab != -1 && topicId == 0) { this.initialTab = initialTab; } else { @@ -1478,6 +1485,7 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload } } } + onTabProgress(initialTab); info = chatInfo; this.userInfo = userInfo; if (info != null) { @@ -1512,6 +1520,7 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.channelRecommendationsLoaded); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.savedMessagesDialogsUpdate); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.dialogsNeedReload); + profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.starUserGiftsLoaded); for (int a = 0; a < 10; a++) { //cellCache.add(new SharedPhotoVideoCell(context)); @@ -2274,6 +2283,8 @@ public int getStartedTrackingX() { return startedTrackingX; } }; + } else if (profileActivity instanceof ProfileActivity) { + giftsContainer = new ProfileGiftsContainer(context, profileActivity.getCurrentAccount(), ((ProfileActivity) profileActivity).getDialogId(), resourcesProvider); } setWillNotDraw(false); @@ -3051,6 +3062,7 @@ protected void onDraw(Canvas canvas) { if (!start) { requestLayout(); } + setVisibleHeight(lastVisibleHeight); }); addView(scrollSlidingTextTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); @@ -3931,7 +3943,7 @@ private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerListView recyclerV if (lastVisiblePosition + 1 >= profileActivity.getMessagesController().getSavedMessagesController().getLoadedCount()) { profileActivity.getMessagesController().getSavedMessagesController().loadDialogs(false); } - } else if (mediaPage.selectedType != TAB_RECOMMENDED_CHANNELS && mediaPage.selectedType != TAB_SAVED_MESSAGES && mediaPage.selectedType != TAB_BOT_PREVIEWS) { + } else if (mediaPage.selectedType != TAB_RECOMMENDED_CHANNELS && mediaPage.selectedType != TAB_SAVED_MESSAGES && mediaPage.selectedType != TAB_BOT_PREVIEWS && mediaPage.selectedType != TAB_GIFTS) { final int threshold; if (mediaPage.selectedType == 0) { threshold = 3; @@ -4116,6 +4128,7 @@ public void onDestroy() { profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.channelRecommendationsLoaded); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.savedMessagesDialogsUpdate); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.dialogsNeedReload); + profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.starUserGiftsLoaded); if (searchTagsList != null) { searchTagsList.detach(); } @@ -4766,6 +4779,9 @@ public RecyclerListView getCurrentListView() { if (mediaPages[0].selectedType == TAB_BOT_PREVIEWS) { return botPreviewsContainer.getCurrentListView(); } + if (mediaPages[0].selectedType == TAB_GIFTS) { + return giftsContainer.getCurrentListView(); + } if (mediaPages[0].selectedType == TAB_SAVED_MESSAGES && savedMessagesContainer != null) { return savedMessagesContainer.chatActivity.getChatListView(); } @@ -5009,7 +5025,9 @@ public boolean closeActionMode(boolean uncheckAnimated) { } } + private int lastVisibleHeight; public void setVisibleHeight(int height) { + lastVisibleHeight = height; for (int a = 0; a < mediaPages.length; a++) { float t = -(getMeasuredHeight() - Math.max(height, dp(mediaPages[a].selectedType == TAB_STORIES ? 280 : 120))) / 2f; mediaPages[a].emptyView.setTranslationY(t); @@ -5018,6 +5036,13 @@ public void setVisibleHeight(int height) { if (botPreviewsContainer != null) { botPreviewsContainer.setVisibleHeight(height); } + if (giftsContainer != null) { + int h = height - dp(48); + if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { + h -= fragmentContextView.getHeight() - dp(2.5f); + } + giftsContainer.setVisibleHeight(h); + } } protected void onActionModeSelectedUpdate(SparseArray messageObjects) { @@ -5489,6 +5514,11 @@ public void didReceivedNotification(int id, int account, Object... args) { } } else if (id == NotificationCenter.dialogsNeedReload) { savedDialogsAdapter.update(true); + } else if (id == NotificationCenter.starUserGiftsLoaded) { + long dialogId = (long) args[0]; + if (dialogId == dialog_id) { + updateTabs(true); + } } } @@ -5784,6 +5814,7 @@ public void setMergeDialogId(long did) { mergeDialogId = did; } + private long giftsLastHash; private void updateTabs(boolean animated) { if (scrollSlidingTextTabStrip == null) { return; @@ -5798,6 +5829,7 @@ private void updateTabs(boolean animated) { boolean hasEditBotPreviews = user != null && user.bot && user.bot_has_main_app && user.bot_can_edit; boolean hasBotPreviews = user != null && user.bot && !user.bot_can_edit && (userInfo != null && userInfo.bot_info != null && userInfo.bot_info.has_preview_medias) && !hasEditBotPreviews; boolean hasStories = (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(); + boolean hasGifts = giftsContainer != null && userInfo != null && userInfo.stargifts_count > 0; int changed = 0; if ((hasStories || hasBotPreviews) != scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) { changed++; @@ -5808,6 +5840,11 @@ private void updateTabs(boolean animated) { if (isSearchingStories() != scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) { changed++; } + if (hasGifts != scrollSlidingTextTabStrip.hasTab(TAB_GIFTS)) { + changed++; + } else if (giftsContainer != null && hasGifts && giftsLastHash != giftsContainer.getLastEmojisHash()) { + changed++; + } if (!isStoriesView()) { if ((chatUsersAdapter.chatInfo == null) == scrollSlidingTextTabStrip.hasTab(TAB_GROUPUSERS)) { changed++; @@ -5923,6 +5960,12 @@ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues sta } } } + if (hasGifts) { + if (!scrollSlidingTextTabStrip.hasTab(TAB_GIFTS)) { + scrollSlidingTextTabStrip.addTextTab(TAB_GIFTS, TextUtils.concat(getString(R.string.ProfileGifts), giftsContainer.getLastEmojis(null)), idToView); + giftsLastHash = giftsContainer.getLastEmojisHash(); + } + } if (!isStoriesView()) { if (hasSavedDialogs) { if (!scrollSlidingTextTabStrip.hasTab(TAB_SAVED_DIALOGS)) { @@ -6245,6 +6288,15 @@ private void switchToCurrentSelectedMode(boolean animated) { AndroidUtilities.removeFromParent(botPreviewsContainer); mediaPages[a].addView(botPreviewsContainer); } + } else if (mediaPages[a].selectedType == TAB_GIFTS) { + if (currentAdapter != null) { + recycleAdapter(currentAdapter); + mediaPages[a].listView.setAdapter(null); + } + if (giftsContainer != null && giftsContainer.getParent() != mediaPages[a]) { + AndroidUtilities.removeFromParent(giftsContainer); + mediaPages[a].addView(giftsContainer); + } } if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { mediaPages[a].listView.setItemAnimator(mediaPages[a].itemAnimator); @@ -6261,6 +6313,9 @@ private void switchToCurrentSelectedMode(boolean animated) { if (botPreviewsContainer != null && mediaPages[a].selectedType != TAB_BOT_PREVIEWS && botPreviewsContainer.getParent() == mediaPages[a]) { mediaPages[a].removeView(botPreviewsContainer); } + if (giftsContainer != null && mediaPages[a].selectedType != TAB_GIFTS && giftsContainer.getParent() == mediaPages[a]) { + mediaPages[a].removeView(giftsContainer); + } if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_SAVED_DIALOGS || mediaPages[a].selectedType == TAB_STORIES || mediaPages[a].selectedType == TAB_ARCHIVED_STORIES || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers() || mediaPages[a].selectedType == TAB_RECOMMENDED_CHANNELS || mediaPages[a].selectedType == TAB_BOT_PREVIEWS) { if (animated) { searchItemState = 2; @@ -6319,6 +6374,8 @@ private void switchToCurrentSelectedMode(boolean animated) { } else if (mediaPages[a].selectedType == TAB_BOT_PREVIEWS) { + } else if (mediaPages[a].selectedType == TAB_GIFTS) { + } else { if (!sharedMediaData[mediaPages[a].selectedType].loading && !sharedMediaData[mediaPages[a].selectedType].endReached[0] && sharedMediaData[mediaPages[a].selectedType].messages.isEmpty()) { sharedMediaData[mediaPages[a].selectedType].loading = true; @@ -6404,10 +6461,10 @@ private boolean onItemLongClick(MessageObject item, View view, int a) { } deleteItem.setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); if (gotoItem != null) { - gotoItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS ? View.VISIBLE : View.GONE); + gotoItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS && getClosestTab() != TAB_GIFTS ? View.VISIBLE : View.GONE); } if (forwardItem != null) { - forwardItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS ? View.VISIBLE : View.GONE); + forwardItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS && getClosestTab() != TAB_GIFTS ? View.VISIBLE : View.GONE); } selectedMessagesCountTextView.setNumber(1, false); AnimatorSet animatorSet = new AnimatorSet(); @@ -6472,10 +6529,10 @@ private void onItemClick(int index, View view, MessageObject message, int a, int selectedMessagesCountTextView.setNumber(selectedFiles[0].size() + selectedFiles[1].size(), true); deleteItem.setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); if (gotoItem != null) { - gotoItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS && selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); + gotoItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS && getClosestTab() != TAB_GIFTS && selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); } if (forwardItem != null) { - forwardItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS ? View.VISIBLE : View.GONE); + forwardItem.setVisibility(getClosestTab() != TAB_STORIES && getClosestTab() != TAB_BOT_PREVIEWS && getClosestTab() != TAB_GIFTS ? View.VISIBLE : View.GONE); } updateStoriesPinButton(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java index 3dbd127c73..71d4cc15bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -220,8 +220,8 @@ protected void onDraw(Canvas canvas) { if (drawable instanceof MotionBackgroundDrawable) { MotionBackgroundDrawable motionBackgroundDrawable = (MotionBackgroundDrawable) drawable; if (motionBackgroundDrawable.hasPattern()) { - int actionBarHeight = (isActionBarVisible() ? ActionBar.getCurrentActionBarHeight() : 0) + (Build.VERSION.SDK_INT >= 21 && occupyStatusBar ? AndroidUtilities.statusBarHeight : 0); - int viewHeight = getRootView().getMeasuredHeight() - actionBarHeight; + int actionBarHeight = (isActionBarVisible() ? ActionBar.getCurrentActionBarHeight() : 0) + (isStatusBarVisible() && Build.VERSION.SDK_INT >= 21 && occupyStatusBar ? AndroidUtilities.statusBarHeight : 0); + int viewHeight = useRootView() ? getRootView().getMeasuredHeight() - actionBarHeight : getHeight(); float scaleX = (float) getMeasuredWidth() / (float) drawable.getIntrinsicWidth(); float scaleY = (float) (viewHeight) / (float) drawable.getIntrinsicHeight(); float scale = Math.max(scaleX, scaleY); @@ -286,8 +286,8 @@ protected void onDraw(Canvas canvas) { checkSnowflake(canvas); canvas.restore(); } else { - int actionBarHeight = (isActionBarVisible() ? ActionBar.getCurrentActionBarHeight() : 0) + (Build.VERSION.SDK_INT >= 21 && occupyStatusBar ? AndroidUtilities.statusBarHeight : 0); - int viewHeight = getRootView().getMeasuredHeight() - actionBarHeight; + int actionBarHeight = (isActionBarVisible() ? ActionBar.getCurrentActionBarHeight() : 0) + (isStatusBarVisible() && Build.VERSION.SDK_INT >= 21 && occupyStatusBar ? AndroidUtilities.statusBarHeight : 0); + int viewHeight = useRootView() ? getRootView().getMeasuredHeight() - actionBarHeight : getHeight(); float scaleX = (float) getMeasuredWidth() / (float) drawable.getIntrinsicWidth(); float scaleY = (float) (viewHeight) / (float) drawable.getIntrinsicHeight(); float scale = Math.max(scaleX, scaleY); @@ -548,10 +548,18 @@ private void checkSnowflake(Canvas canvas) { } } + protected boolean useRootView() { + return true; + } + protected boolean isActionBarVisible() { return true; } + protected boolean isStatusBarVisible() { + return true; + } + protected AdjustPanLayoutHelper createAdjustPanLayoutHelper() { return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StarAppsSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StarAppsSheet.java index e31ded9467..92fa327766 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StarAppsSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StarAppsSheet.java @@ -2,14 +2,12 @@ import static org.telegram.messenger.LocaleController.getString; -import android.app.Dialog; import android.content.Context; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -37,7 +35,7 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { position--; Object obj = adapter.getObject(position); if (obj instanceof TLRPC.User) { - MessagesController.getInstance(currentAccount).openApp(attachedFragment, (TLRPC.User) obj, 0, null); + MessagesController.getInstance(currentAccount).openApp(attachedFragment, (TLRPC.User) obj, null, 0, null); } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java index 0542753881..ed2e71bbee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java @@ -22,6 +22,7 @@ import org.telegram.messenger.LiteMode; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -267,6 +268,11 @@ protected void onDetachedFromWindow() { } private void setSticker() { + if (stickerType == STICKER_TYPE_NO_CONTACTS || stickerType == STICKER_TYPE_SEARCH) { + stickerView.setImageDrawable(new RLottieDrawable(R.raw.utyan_empty, "utyan_empty", dp(130), dp(130))); + return; + } + String imageFilter = null; TLRPC.Document document = null; TLRPC.TL_messages_stickerSet set = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TableView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TableView.java index ab345bacdb..6272372792 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TableView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TableView.java @@ -24,7 +24,11 @@ import androidx.annotation.NonNull; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +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.UserObject; import org.telegram.messenger.Utilities; @@ -34,8 +38,12 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.AvatarSpan; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.spoilers.SpoilersTextView; import org.telegram.ui.LaunchActivity; +import java.util.ArrayList; +import java.util.Date; + public class TableView extends TableLayout { private final Theme.ResourcesProvider resourcesProvider; @@ -65,7 +73,7 @@ public void addRow(CharSequence title, View content) { addView(row); } - public void addRowUnpadded(CharSequence title, View content) { + public TableRow addRowUnpadded(CharSequence title, View content) { TableRow row = new TableRow(getContext()); TableRow.LayoutParams lp; lp = new TableRow.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); @@ -73,10 +81,15 @@ public void addRowUnpadded(CharSequence title, View content) { lp = new TableRow.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f); row.addView(new TableRowContent(this, content, true), lp); addView(row); + return row; } - public void addRowUser(CharSequence title, final int currentAccount, final long did, Runnable onClick) { - final LinkSpanDrawable.LinksTextView textView = new LinkSpanDrawable.LinksTextView(getContext(), resourcesProvider); + public TableRow addRowUser(CharSequence title, final int currentAccount, final long did, Runnable onClick) { + return addRowUser(title, currentAccount, did, onClick, null, null); + } + + public TableRow addRowUser(CharSequence title, final int currentAccount, final long did, Runnable onClick, CharSequence buttonText, Runnable buttonOnClick) { + final ButtonSpan.TextViewButtons textView = new ButtonSpan.TextViewButtons(getContext(), resourcesProvider); textView.setPadding(dp(12.66f), dp(9.33f), dp(12.66f), dp(9.33f)); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); @@ -87,8 +100,17 @@ public void addRowUser(CharSequence title, final int currentAccount, final long AvatarSpan avatarSpan = new AvatarSpan(textView, currentAccount, 24); CharSequence username; boolean deleted = false; + boolean clickable = true; final boolean unknown; - if (UserObject.isService(did)) { + if (did == UserObject.ANONYMOUS) { + deleted = false; + clickable = false; + unknown = true; + username = getString(R.string.StarsTransactionHidden); + CombinedDrawable iconDrawable = getPlatformDrawable("anonymous"); + iconDrawable.setIconSize(dp(16), dp(16)); + avatarSpan.setImageDrawable(iconDrawable); + } else if (UserObject.isService(did)) { deleted = false; unknown = true; username = getString(R.string.StarsTransactionUnknown); @@ -110,22 +132,32 @@ public void addRowUser(CharSequence title, final int currentAccount, final long } SpannableStringBuilder ssb = new SpannableStringBuilder("x " + username); ssb.setSpan(avatarSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.setSpan(new ClickableSpan() { - @Override - public void onClick(@NonNull View widget) { - if (onClick != null) { - onClick.run(); + if (clickable) { + ssb.setSpan(new ClickableSpan() { + @Override + public void onClick(@NonNull View widget) { + if (onClick != null) { + onClick.run(); + } } - } - @Override - public void updateDrawState(@NonNull TextPaint ds) { - ds.setUnderlineText(false); - } - }, 3, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + @Override + public void updateDrawState(@NonNull TextPaint ds) { + ds.setUnderlineText(false); + } + }, 3, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (buttonText != null) { + ssb.append(" ").append(ButtonSpan.make(buttonText, buttonOnClick, resourcesProvider)); + } textView.setText(ssb); if (!deleted) { - addRowUnpadded(title, textView); + return addRowUnpadded(title, textView); } + return null; + } + + public TableRow addRowDateTime(CharSequence title, int date) { + return addRow(title, LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterGiveawayCard().format(new Date(date * 1000L)), LocaleController.getInstance().getFormatterDay().format(new Date(date * 1000L)))); } public void addRowLink(CharSequence title, CharSequence value, Runnable onClick) { @@ -154,8 +186,8 @@ public void updateDrawState(@NonNull TextPaint ds) { addRowUnpadded(title, textView); } - public void addRow(CharSequence title, CharSequence text) { - TextView textView = new TextView(getContext()); + public TableRow addRow(CharSequence title, CharSequence text) { + ButtonSpan.TextViewButtons textView = new ButtonSpan.TextViewButtons(getContext()); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setText(text); @@ -167,6 +199,43 @@ public void addRow(CharSequence title, CharSequence text) { lp = new TableRow.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f); row.addView(new TableRowContent(this, textView), lp); addView(row); + + return row; + } + + public void addFullRow(CharSequence text) { + SpoilersTextView textView = new SpoilersTextView(getContext()); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false); + textView.setText(text); + NotificationCenter.listenEmojiLoading(textView); + + TableRow row = new TableRow(getContext()); + TableRow.LayoutParams lp; + lp = new TableRow.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.span = 2; + row.addView(new TableRowFullContent(this, textView), lp); + addView(row); + } + + public void addFullRow(CharSequence text, ArrayList entities) { + AnimatedEmojiSpan.TextViewEmojis textView = new AnimatedEmojiSpan.TextViewEmojis(getContext()); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + text = new SpannableStringBuilder(text); + MessageObject.addEntitiesToText(text, entities, false, false, false, false); + text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false); + text = MessageObject.replaceAnimatedEmoji(text, entities, textView.getPaint().getFontMetricsInt()); + textView.setText(text); + NotificationCenter.listenEmojiLoading(textView); + + TableRow row = new TableRow(getContext()); + TableRow.LayoutParams lp; + lp = new TableRow.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.span = 2; + row.addView(new TableRowFullContent(this, textView), lp); + addView(row); } public static class TableRowTitle extends TextView { @@ -217,6 +286,56 @@ protected void onDraw(Canvas canvas) { } } + public static class TableRowFullContent extends FrameLayout { + + private final TableView table; + private final Theme.ResourcesProvider resourcesProvider; + + public TableRowFullContent(TableView table, View content) { + this(table, content, false); + } + + public TableRowFullContent(TableView table, View content, boolean unpadded) { + super(table.getContext()); + this.table = table; + this.resourcesProvider = table.resourcesProvider; + + setWillNotDraw(false); + if (!unpadded) { + setPadding(dp(12.66f), dp(9.33f), dp(12.66f), dp(9.33f)); + } + addView(content, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } + + private boolean first, last; + + public void setFirstLast(boolean first, boolean last) { + if (this.first != first || this.last != last) { + this.first = first; + this.last = last; + invalidate(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (first || last) { + final float r = dp(4); + table.radii[0] = table.radii[1] = first ? r : 0; // top left + table.radii[2] = table.radii[3] = first ? r : 0; // top right + table.radii[4] = table.radii[5] = last ? r : 0; // bottom right + table.radii[6] = table.radii[7] = last ? r : 0; // bottom left + table.path.rewind(); + AndroidUtilities.rectTmp.set(table.hw, table.hw, getWidth() - table.hw, getHeight() + table.hw * dp(last ? -1f : +1f)); + table.path.addRoundRect(AndroidUtilities.rectTmp, table.radii, Path.Direction.CW); + canvas.drawPath(table.path, table.borderPaint); + } else { + canvas.drawRect(table.hw, table.hw, getWidth() - table.hw, getHeight() + table.hw, table.borderPaint); + } + super.onDraw(canvas); + } + } + public static class TableRowContent extends FrameLayout { private final TableView table; @@ -289,6 +408,8 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { ((TableRowTitle) child).setFirstLast(y == 0, y == height - 1); } else if (child instanceof TableRowContent) { ((TableRowContent) child).setFirstLast(y == 0, y == height - 1); + } else if (child instanceof TableRowFullContent) { + ((TableRowFullContent) child).setFirstLast(y == 0, y == height - 1); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java index bec5cae449..2a8b8f86b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java @@ -23,16 +23,22 @@ public class Text { - private final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final TextPaint paint; private StaticLayout layout; private float width, left; private float maxWidth = 999999; + public Text(CharSequence text, TextPaint paint) { + this.paint = paint; + setText(text); + } + public Text(CharSequence text, float textSizeDp) { this(text, textSizeDp, null); } public Text(CharSequence text, float textSizeDp, Typeface typeface) { + paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); paint.setTextSize(dp(textSizeDp)); paint.setTypeface(typeface); setText(text); 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 e3a6cd585a..6423568793 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java @@ -32,6 +32,8 @@ public class UItem extends AdapterWithDiffUtils.Item { + public static final int MAX_SPAN_COUNT = -1; + public View view; public int id; public boolean checked; @@ -44,6 +46,7 @@ public class UItem extends AdapterWithDiffUtils.Item { public CharSequence animatedText; public String[] texts; public boolean accent, red, transparent, locked; + public int spanCount = MAX_SPAN_COUNT; public boolean include; public long dialogId; @@ -51,6 +54,7 @@ public class UItem extends AdapterWithDiffUtils.Item { public int flags; public int intValue; + public float floatValue; public long longValue; public Utilities.Callback intCallback; @@ -505,6 +509,11 @@ public UItem accent() { return this; } + public UItem setSpanCount(int spanCount) { + this.spanCount = spanCount; + return this; + } + public > boolean instanceOf(Class factoryClass) { if (viewType < factoryViewTypeStartsWith) return false; if (factoryInstances == null) return false; @@ -575,6 +584,7 @@ public boolean itemEquals(UItem item) { TextUtils.equals(textValue, item.textValue) && view == item.view && intValue == item.intValue && + Math.abs(floatValue - item.floatValue) < 0.01f && longValue == item.longValue && Objects.equals(object, item.object) && Objects.equals(object2, item.object2) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalRecyclerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalRecyclerView.java index 6ccc260929..960fa15412 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalRecyclerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalRecyclerView.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -21,7 +22,7 @@ public class UniversalRecyclerView extends RecyclerListView { - public final LinearLayoutManager layoutManager; + public LinearLayoutManager layoutManager; public final UniversalAdapter adapter; private ItemTouchHelper itemTouchHelper; @@ -68,16 +69,52 @@ public UniversalRecyclerView( Utilities.Callback5 onClick, Utilities.Callback5Return onLongClick, Theme.ResourcesProvider resourcesProvider + ) { + this(context, currentAccount, classGuid, dialog, fillItems, onClick, onLongClick, resourcesProvider, UItem.MAX_SPAN_COUNT); + } + + public UniversalRecyclerView( + Context context, + int currentAccount, + int classGuid, + boolean dialog, + Utilities.Callback2, UniversalAdapter> fillItems, + Utilities.Callback5 onClick, + Utilities.Callback5Return onLongClick, + Theme.ResourcesProvider resourcesProvider, + int spansCount ) { super(context, resourcesProvider); - setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { - @Override - protected int getExtraLayoutSpace(State state) { - if (doNotDetachViews) return AndroidUtilities.displaySize.y; - return super.getExtraLayoutSpace(state); - } - }); + if (spansCount == UItem.MAX_SPAN_COUNT) { + setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { + @Override + protected int getExtraLayoutSpace(State state) { + if (doNotDetachViews) return AndroidUtilities.displaySize.y; + return super.getExtraLayoutSpace(state); + } + }); + } else { + ExtendedGridLayoutManager layoutManager1 = new ExtendedGridLayoutManager(context, spansCount) { + @Override + protected int getExtraLayoutSpace(State state) { + if (doNotDetachViews) return AndroidUtilities.displaySize.y; + return super.getExtraLayoutSpace(state); + } + }; + layoutManager1.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (adapter == null) + return layoutManager1.getSpanCount(); + final UItem item = adapter.getItem(position); + if (item == null || item.spanCount == UItem.MAX_SPAN_COUNT) + return layoutManager1.getSpanCount(); + return item.spanCount; + } + }); + setLayoutManager(layoutManager = layoutManager1); + } setAdapter(adapter = new UniversalAdapter(this, context, currentAccount, classGuid, dialog, fillItems, resourcesProvider)); if (onClick != null) { @@ -110,6 +147,32 @@ protected void onMoveAnimationUpdate(ViewHolder holder) { setItemAnimator(itemAnimator); } + public void setSpanCount(int spanCount) { + if (layoutManager instanceof ExtendedGridLayoutManager) { + ((ExtendedGridLayoutManager) layoutManager).setSpanCount(spanCount); + } else if (layoutManager instanceof LinearLayoutManager && spanCount != UItem.MAX_SPAN_COUNT) { + ExtendedGridLayoutManager layoutManager1 = new ExtendedGridLayoutManager(getContext(), spanCount) { + @Override + protected int getExtraLayoutSpace(State state) { + if (doNotDetachViews) return AndroidUtilities.displaySize.y; + return super.getExtraLayoutSpace(state); + } + }; + layoutManager1.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (adapter == null) + return layoutManager1.getSpanCount(); + final UItem item = adapter.getItem(position); + if (item == null || item.spanCount == UItem.MAX_SPAN_COUNT) + return layoutManager1.getSpanCount(); + return item.spanCount; + } + }); + setLayoutManager(layoutManager = layoutManager1); + } + } + private boolean reorderingAllowed; public void listenReorder( Utilities.Callback2> onReordered diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java index c6cb67fe13..35d1ace763 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java @@ -8,22 +8,30 @@ package org.telegram.ui.Components; -import static com.google.android.exoplayer2.C.TRACK_TYPE_AUDIO; +import static org.telegram.messenger.LocaleController.getString; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.SurfaceTexture; import android.media.AudioManager; +import android.media.MediaCodecInfo; +import android.media.MediaCodecList; import android.media.MediaFormat; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; +import android.text.TextUtils; +import android.util.Base64; +import android.util.LongSparseArray; import android.view.Surface; import android.view.SurfaceView; import android.view.TextureView; import android.view.ViewGroup; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; @@ -32,7 +40,6 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; @@ -45,17 +52,22 @@ import com.google.android.exoplayer2.audio.DefaultAudioSink; import com.google.android.exoplayer2.audio.TeeAudioProcessor; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; +import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.source.LoopingMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.source.TrackGroup; +import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; +import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector; -import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.trackselection.TrackSelectionOverride; +import com.google.android.exoplayer2.trackselection.TrackSelectionParameters; import com.google.android.exoplayer2.upstream.DefaultAllocator; -import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.video.SurfaceNotValidException; import com.google.android.exoplayer2.video.VideoListener; import com.google.android.exoplayer2.video.VideoSize; @@ -64,13 +76,27 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.FourierTransform; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.Utilities; import org.telegram.messenger.secretmedia.ExtendedDefaultDataSourceFactory; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.Stories.recorder.StoryEntry; +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; @SuppressLint("NewApi") public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsListener, NotificationCenter.NotificationCenterDelegate { @@ -95,7 +121,7 @@ default void onRenderedFirstFrame(EventTime eventTime) { default void onSeekStarted(EventTime eventTime) { } - default void onSeekFinished(EventTime eventTime) { + default void onSeekFinished(AnalyticsListener.EventTime eventTime) { } } @@ -107,8 +133,9 @@ public interface AudioVisualizerDelegate { public ExoPlayer player; private ExoPlayer audioPlayer; + private DefaultBandwidthMeter bandwidthMeter; private MappingTrackSelector trackSelector; - private DataSource.Factory mediaDataSourceFactory; + private ExtendedDefaultDataSourceFactory mediaDataSourceFactory; private TextureView textureView; private SurfaceView surfaceView; private Surface surface; @@ -130,6 +157,9 @@ public interface AudioVisualizerDelegate { private int lastReportedPlaybackState; private boolean lastReportedPlayWhenReady; + private ArrayList videoQualities; + private Quality videoQualityToSelect; + private ArrayList manifestUris; private Uri videoUri, audioUri; private String videoType, audioType; private boolean loopingMediaSource; @@ -154,9 +184,9 @@ public VideoPlayer() { public VideoPlayer(boolean pauseOther, boolean audioDisabled) { this.audioDisabled = audioDisabled; mediaDataSourceFactory = new ExtendedDefaultDataSourceFactory(ApplicationLoader.applicationContext, "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20150101 Firefox/47.0 (Chrome)"); - trackSelector = new DefaultTrackSelector(ApplicationLoader.applicationContext); + trackSelector = new DefaultTrackSelector(ApplicationLoader.applicationContext, new AdaptiveTrackSelection.Factory()); if (audioDisabled) { - trackSelector.setParameters(trackSelector.getParameters().buildUpon().setTrackTypeDisabled(TRACK_TYPE_AUDIO, true).build()); + trackSelector.setParameters(trackSelector.getParameters().buildUpon().setTrackTypeDisabled(C.TRACK_TYPE_AUDIO, true).build()); } lastReportedPlaybackState = ExoPlayer.STATE_IDLE; shouldPauseOther = pauseOther; @@ -247,11 +277,14 @@ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { } public void preparePlayerLoop(Uri videoUri, String videoType, Uri audioUri, String audioType) { + this.videoQualities = null; + this.videoQualityToSelect = null; this.videoUri = videoUri; this.audioUri = audioUri; this.videoType = videoType; this.audioType = audioType; this.loopingMediaSource = true; + currentStreamIsHls = false; mixedAudio = true; audioPlayerReady = false; @@ -314,11 +347,14 @@ public void preparePlayer(Uri uri, String type) { } public void preparePlayer(Uri uri, String type, int priority) { + this.videoQualities = null; + this.videoQualityToSelect = null; this.videoUri = uri; this.videoType = type; this.audioUri = null; this.audioType = null; this.loopingMediaSource = false; + currentStreamIsHls = false; videoPlayerReady = false; mixedAudio = false; @@ -331,6 +367,612 @@ public void preparePlayer(Uri uri, String type, int priority) { player.prepare(); } + public void preparePlayer(ArrayList uris, Quality select) { + this.videoQualities = uris; + this.videoQualityToSelect = select; + this.videoUri = null; + this.videoType = "hls"; + this.audioUri = null; + this.audioType = null; + this.loopingMediaSource = false; + + videoPlayerReady = false; + mixedAudio = false; + currentUri = null; + isStreaming = true; + ensurePlayerCreated(); + + currentStreamIsHls = false; + setSelectedQuality(true, select); + } + + public static Quality getSavedQuality(ArrayList qualities, MessageObject messageObject) { + if (messageObject == null) return null; + return getSavedQuality(qualities, messageObject.getDialogId(), messageObject.getId()); + } + + public static Quality getSavedQuality(ArrayList qualities, long did, int mid) { + final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("media_saved_pos", Activity.MODE_PRIVATE); + final String setting = preferences.getString(did + "_" + mid + "q2", ""); + if (TextUtils.isEmpty(setting)) return null; + for (Quality q : qualities) { + final String idx = q.width + "x" + q.height + (q.original ? "s" : ""); + if (TextUtils.equals(setting, idx)) return q; + } + return null; + } + + public static void saveQuality(Quality q, MessageObject messageObject) { + if (messageObject == null) return; + saveQuality(q, messageObject.getDialogId(), messageObject.getId()); + } + + public static void saveQuality(Quality q, long did, int mid) { + final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("media_saved_pos", Activity.MODE_PRIVATE); + final SharedPreferences.Editor editor = preferences.edit(); + if (q == null) { + editor.remove(did + "_" + mid + "q2"); + } else { + editor.putString(did + "_" + mid + "q2", q.width + "x" + q.height + (q.original ? "s" : "")); + } + editor.apply(); + } + + public static final int QUALITY_AUTO = -1; // HLS + private int selectedQualityIndex = QUALITY_AUTO; + private boolean currentStreamIsHls; + + public Quality getQuality(int index) { + if (videoQualities == null) return getHighestQuality(false); + if (index < 0 || index >= videoQualities.size()) return getHighestQuality(false); + return videoQualities.get(index); + } + + public Quality getHighestQuality(Boolean original) { + Quality max = null; + for (int i = 0; i < getQualitiesCount(); ++i) { + final Quality q = getQuality(i); + if (original != null && q.original != original) continue; + if (max == null || max.width * max.height < q.width * q.height) { + max = q; + } + } + return max; + } + + public int getHighestQualityIndex(Boolean original) { + int maxIndex = -1; + Quality max = null; + for (int i = 0; i < getQualitiesCount(); ++i) { + final Quality q = getQuality(i); + if (original != null && q.original != original) continue; + if (max == null || max.width * max.height < q.width * q.height) { + max = q; + maxIndex = i; + } + } + return maxIndex; + } + + public Quality getLowestQuality() { + Quality min = null; + for (int i = 0; i < getQualitiesCount(); ++i) { + final Quality q = getQuality(i); + if (min == null || min.width * min.height > q.width * q.height) { + min = q; + } + } + return min; + } + + public int getQualitiesCount() { + if (videoQualities == null) return 0; + return videoQualities.size(); + } + + public int getSelectedQuality() { + return selectedQualityIndex; + } + + public int getCurrentQualityIndex() { + if (selectedQualityIndex == QUALITY_AUTO) { + try { + final MappingTrackSelector.MappedTrackInfo mapTrackInfo = trackSelector.getCurrentMappedTrackInfo(); + for (int renderIndex = 0; renderIndex < mapTrackInfo.getRendererCount(); ++renderIndex) { + final TrackGroupArray trackGroups = mapTrackInfo.getTrackGroups(renderIndex); + for (int groupIndex = 0; groupIndex < trackGroups.length; ++groupIndex) { + final TrackGroup trackGroup = trackGroups.get(groupIndex); + for (int trackIndex = 0; trackIndex < trackGroup.length; ++trackIndex) { + final Format format = trackGroup.getFormat(trackIndex); + int formatIndex; + try { + formatIndex = Integer.parseInt(format.id); + } catch (Exception e) { + formatIndex = -1; + } + if (formatIndex >= 0) { + int formatOrder = 0; + for (int j = 0; j < getQualitiesCount(); ++j) { + final Quality q = getQuality(j); + for (int i = 0; i < q.uris.size(); ++i){ + if (q.uris.get(i).m3u8uri != null) { + if (formatOrder == formatIndex) { + return j; + } + formatOrder++; + } + } + } + } + for (int j = 0; j < getQualitiesCount(); ++j) { + final Quality q = getQuality(j); + if (format.width == q.width && format.height == q.height) { + return j; + } + } + } + } + } + } catch (Exception e) { + return -1; + } + } + return selectedQualityIndex; + } + + private TrackSelectionOverride getQualityTrackSelection(VideoUri videoUri) { + try { + int qualityOrder = manifestUris.indexOf(videoUri); + final MappingTrackSelector.MappedTrackInfo mapTrackInfo = trackSelector.getCurrentMappedTrackInfo(); + for (int renderIndex = 0; renderIndex < mapTrackInfo.getRendererCount(); ++renderIndex) { + final TrackGroupArray trackGroups = mapTrackInfo.getTrackGroups(renderIndex); + for (int groupIndex = 0; groupIndex < trackGroups.length; ++groupIndex) { + final TrackGroup trackGroup = trackGroups.get(groupIndex); + for (int trackIndex = 0; trackIndex < trackGroup.length; ++trackIndex) { + final Format format = trackGroup.getFormat(trackIndex); + + int formatIndex; + try { + formatIndex = Integer.parseInt(format.id); + } catch (Exception e) { + formatIndex = -1; + } + if (formatIndex >= 0) { + if (qualityOrder == formatIndex) { + return new TrackSelectionOverride(trackGroup, trackIndex); + } + } + if (format.width == videoUri.width && format.height == videoUri.height) { + return new TrackSelectionOverride(trackGroup, trackIndex); + } + } + } + } + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + + @Override + public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) { + Player.Listener.super.onTrackSelectionParametersChanged(parameters); + if (onQualityChangeListener != null) { + AndroidUtilities.runOnUIThread(onQualityChangeListener); + } + } + + private long fallbackDuration = C.TIME_UNSET; + private long fallbackPosition = C.TIME_UNSET; + + public void setSelectedQuality(int index) { + if (player == null) return; + if (index != selectedQualityIndex) { + selectedQualityIndex = index; + Quality q = null; + if (videoQualities != null && index >= 0 && index < videoQualities.size()) q = videoQualities.get(index); + setSelectedQuality(false, q); + } + } + + private void setSelectedQuality(boolean start, Quality quality) { + if (player == null) return; + + final boolean lastPlaying = player.isPlaying(); + final long lastPosition = player.getCurrentPosition(); + if (!start) { + fallbackPosition = lastPosition; + fallbackDuration = player.getDuration(); + } + + boolean reset = false; + + videoQualityToSelect = quality; + if (quality == null) { // AUTO + final Uri hlsManifest = makeManifest(videoQualities); + if (hlsManifest != null) { + trackSelector.setParameters(trackSelector.getParameters().buildUpon().clearOverrides().build()); + if (!currentStreamIsHls) { + currentStreamIsHls = true; + player.setMediaSource(mediaSourceFromUri(hlsManifest, "hls"), false); + reset = true; + } + } else { + quality = getHighestQuality(true); + if (quality == null) quality = getHighestQuality(false); + if (quality == null || quality.uris.isEmpty()) return; + currentStreamIsHls = false; + videoQualityToSelect = quality; + player.setMediaSource(mediaSourceFromUri(quality.uris.get(0).uri, "other"), false); + reset = true; + } + } else { + if (quality.uris.isEmpty()) return; + Uri hlsManifest = null; + if (quality.uris.size() > 1) { + hlsManifest = makeManifest(videoQualities); + } + if (hlsManifest == null || quality.uris.size() == 1) { + currentStreamIsHls = false; + player.setMediaSource(mediaSourceFromUri(quality.uris.get(0).uri, "other"), false); + reset = true; + } else { + if (!currentStreamIsHls) { + currentStreamIsHls = true; + player.setMediaSource(mediaSourceFromUri(hlsManifest, "hls"), false); + reset = true; + } + TrackSelectionParameters.Builder selector = trackSelector.getParameters().buildUpon().clearOverrides(); + for (VideoUri uri : quality.uris) { + TrackSelectionOverride override = getQualityTrackSelection(uri); + if (override == null) continue; + selector.addOverride(override); + } + trackSelector.setParameters(selector.build()); + } + } + + if (reset) { + player.prepare(); + if (!start) { + player.seekTo(lastPosition); + if (lastPlaying) { + player.play(); + } + } + } + } + + public Quality getCurrentQuality() { + final int index = getCurrentQualityIndex(); + if (index < 0 || index >= getQualitiesCount()) return null; + return getQuality(index); + } + + private Runnable onQualityChangeListener; + public void setOnQualityChangeListener(Runnable listener) { + this.onQualityChangeListener = listener; + } + + public static ArrayList getQualities(int currentAccount, TLRPC.Document original, ArrayList alt_documents, int reference, boolean forThumb) { + ArrayList documents = new ArrayList<>(); + if (original != null) { + documents.add(original); + } + if (!MessagesController.getInstance(currentAccount).videoIgnoreAltDocuments && alt_documents != null) { + documents.addAll(alt_documents); + } + + final LongSparseArray manifests = new LongSparseArray<>(); + for (int i = 0; i < documents.size(); ++i) { + final TLRPC.Document document = documents.get(i); + if ("application/x-mpegurl".equalsIgnoreCase(document.mime_type)) { + if (document.file_name_fixed == null || !document.file_name_fixed.startsWith("mtproto")) continue; + try { + long videoDocumentId = Long.parseLong(document.file_name_fixed.substring(7)); + manifests.put(videoDocumentId, document); + documents.remove(i); + i--; + } catch (Exception e) { + FileLog.e(e); + } + } + } + + ArrayList result = new ArrayList<>(); + for (int i = 0; i < documents.size(); ++i) { + try { + final TLRPC.Document document = documents.get(i); + if ("application/x-mpegurl".equalsIgnoreCase(document.mime_type)) { + continue; + } + VideoUri q = VideoUri.of(currentAccount, document, manifests.get(document.id), reference); + if (q.width <= 0 || q.height <= 0) { + continue; + } + if (document == original) { + q.original = true; + } + result.add(q); + } catch (Exception e) { + FileLog.e(e); + } + } + + ArrayList filtered = new ArrayList<>(); + for (int i = 0; i < result.size(); ++i) { + final VideoUri q = result.get(i); + if (q.codec != null) { + if (forThumb) { + if (!("avc".equals(q.codec) || "h264".equals(q.codec) || "h265".equals(q.codec) || "hevc".equals(q.codec) || "vp9".equals(q.codec) || "vp8".equals(q.codec))) { + continue; + } + } else { + if (("av1".equals(q.codec) || "hevc".equals(q.codec) || "vp9".equals(q.codec)) && !supportsHardwareDecoder(q.codec)) { + continue; + } + } + } + filtered.add(q); + } + + ArrayList qualities = new ArrayList<>(); + if (filtered.isEmpty()) + qualities.addAll(result); + else + qualities.addAll(filtered); + + return Quality.groupBy(qualities); + } + + public static boolean hasQualities(int currentAccount, TLRPC.MessageMedia media) { + if (!(media instanceof TLRPC.TL_messageMediaDocument)) + return false; + ArrayList qualities = getQualities(currentAccount, media.document, media.alt_documents, 0, false); + return qualities != null && qualities.size() > 1; + } + + public static TLRPC.Document getDocumentForThumb(int currentAccount, TLRPC.MessageMedia media) { + if (!(media instanceof TLRPC.TL_messageMediaDocument)) + return null; + ArrayList qualities = getQualities(currentAccount, media.document, media.alt_documents, 0, true); + final int MAX_SIZE = 860; + VideoUri uri = null; + for (final Quality q : qualities) { + for (final VideoUri v : q.uris) { + if ((uri == null || uri.width * uri.height < v.width * v.height) && v.width <= MAX_SIZE && v.height <= MAX_SIZE) { + uri = v; + } + } + } + if (uri == null) { + for (final Quality q : qualities) { + for (final VideoUri v : q.uris) { + if ((uri == null || uri.width * uri.height > v.width * v.height)){ + uri = v; + } + } + } + } + return uri == null ? null : uri.document; + } + + public static boolean supportsHardwareDecoder(String codec) { + try { + switch (codec) { + case "h264": + case "avc": codec = "video/avc"; break; + case "vp8": codec = "video/x-vnd.on2.vp8"; break; + case "vp9": codec = "video/x-vnd.on2.vp9"; break; + case "h265": + case "hevc": codec = "video/hevc"; break; + case "av1": case "av01": codec = "video/av01"; break; + default: codec = "video/" + codec; break; + } + final int count = MediaCodecList.getCodecCount(); + for (int i = 0; i < count; i++) { + final MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); + if (info.isEncoder()) continue; + if (!MediaCodecUtil.isHardwareAccelerated(info, codec)) continue; + final String[] supportedTypes = info.getSupportedTypes(); + for (int j = 0; j < supportedTypes.length; ++j) { + if (supportedTypes[j].equalsIgnoreCase(codec)) + return true; + } + } + return false; + } catch (Exception e) { + FileLog.e(e); + return false; + } + } + + public Uri makeManifest(ArrayList qualities) { + final StringBuilder sb = new StringBuilder(); + sb.append("#EXTM3U\n"); + sb.append("#EXT-X-VERSION:6\n"); + sb.append("#EXT-X-INDEPENDENT-SEGMENTS\n\n"); + manifestUris = new ArrayList<>(); + boolean hasManifests = false; + for (Quality q : qualities) { + for (VideoUri v : q.uris) { + mediaDataSourceFactory.putDocumentUri(v.docId, v.uri); + mediaDataSourceFactory.putDocumentUri(v.manifestDocId, v.m3u8uri); + if (v.m3u8uri != null) { + manifestUris.add(v); + sb.append("#EXT-X-STREAM-INF:BANDWIDTH=").append((int) Math.floor(v.bitrate * 8)).append(",RESOLUTION=").append(v.width).append("x").append(v.height); + sb.append("\n"); + sb.append("mtproto:").append(v.manifestDocId).append("\n\n"); + hasManifests = true; + } + } + } + if (!hasManifests) return null; + final String base64 = Base64.encodeToString(sb.toString().getBytes(), Base64.NO_WRAP); + return Uri.parse("data:application/x-mpegurl;base64," + base64); + } + + public static class Quality { + + public boolean original; + public int width, height; + public final ArrayList uris = new ArrayList<>(); + + public Quality(VideoUri uri) { + original = uri.original; + width = uri.width; + height = uri.height; + uris.add(uri); + } + + public static ArrayList groupBy(ArrayList uris) { + final ArrayList qualities = new ArrayList<>(); + + for (VideoUri uri : uris) { + if (uri.original) { + qualities.add(new Quality(uri)); + continue; + } + + Quality q = null; + for (Quality _q : qualities) { + if (!_q.original && _q.width == uri.width && _q.height == uri.height) { + q = _q; + break; + } + } + + if (q != null && !SharedConfig.debugVideoQualities) { + q.uris.add(uri); + } else { + qualities.add(new Quality(uri)); + } + } + + return qualities; + } + + @NonNull + @Override + public String toString() { + if (SharedConfig.debugVideoQualities) { + return width + "x" + height + + (original ? " (" + getString(R.string.QualitySource) + ")" : "") + "\n" + + AndroidUtilities.formatFileSize((long) uris.get(0).bitrate).replace(" ", "") + "/s" + + (uris.get(0).codec != null ? ", " + uris.get(0).codec : ""); + } else { + int p = Math.min(width, height); + if (Math.abs(p - 1080) < 30) p = 1080; + else if (Math.abs(p - 720) < 30) p = 720; + else if (Math.abs(p - 360) < 30) p = 360; + else if (Math.abs(p - 240) < 30) p = 240; + else if (Math.abs(p - 144) < 30) p = 144; + return p + "p" + (original ? " (" + getString(R.string.QualitySource) + ")" : ""); + } + } + + private static final List preferableCodecs_1 = Arrays.asList("h264", "avc"); + private static final ArrayList preferableCodecs_2 = new ArrayList(Arrays.asList("h265", "hevc")); + + public TLRPC.Document getDownloadDocument() { + if (uris.isEmpty()) return null; + for (VideoUri v : uris) { + if (v.codec != null && preferableCodecs_1.contains(v.codec)) { + return v.document; + } + } + for (VideoUri v : uris) { + if (v.codec != null && preferableCodecs_2.contains(v.codec)) { + return v.document; + } + } + return uris.get(0).document; + } + } + + public static class VideoUri { + + public boolean original; + public long docId; + public Uri uri; + public long manifestDocId; + public Uri m3u8uri; + + public TLRPC.Document document; + + public int width, height; + public double duration; + public long size; + public double bitrate; + + public String codec; + public MediaItem mediaItem; + + public static Uri getUri(int currentAccount, TLRPC.Document document, int reference) throws UnsupportedEncodingException { + final String params = + "?account=" + currentAccount + + "&id=" + document.id + + "&hash=" + document.access_hash + + "&dc=" + document.dc_id + + "&size=" + document.size + + "&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") + + "&rid=" + reference + + "&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") + + "&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]); + return Uri.parse("tg://" + MessageObject.getFileName(document) + params); + } + + public static VideoUri of(int currentAccount, TLRPC.Document document, TLRPC.Document manifest, int reference) throws UnsupportedEncodingException { + final VideoUri videoUri = new VideoUri(); + TLRPC.TL_documentAttributeVideo attributeVideo = null; + for (int i = 0; i < document.attributes.size(); ++i) { + final TLRPC.DocumentAttribute attribute = document.attributes.get(i); + if (attribute instanceof TLRPC.TL_documentAttributeVideo) { + attributeVideo = (TLRPC.TL_documentAttributeVideo) attribute; + break; + } + } + final String codec = attributeVideo == null ? null : attributeVideo.video_codec; + + videoUri.document = document; + videoUri.docId = document.id; + videoUri.uri = getUri(currentAccount, document, reference); + if (manifest != null) { + videoUri.manifestDocId = manifest.id; + videoUri.m3u8uri = getUri(currentAccount, manifest, reference); + File file = FileLoader.getInstance(currentAccount).getPathToAttach(manifest, null, false, true); + if (file != null && file.exists()) { +// qualityUri.m3u8uri = Uri.fromFile(file); + } + } + + videoUri.codec = codec; + videoUri.size = document.size; + if (attributeVideo != null) { + videoUri.duration = attributeVideo.duration; + videoUri.width = attributeVideo.w; + videoUri.height = attributeVideo.h; + + videoUri.bitrate = videoUri.size / videoUri.duration; + } + + File file = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, false, true); + if (file != null && file.exists()) { +// qualityUri.uri = Uri.fromFile(file); + } + + return videoUri; + } + + public MediaItem getMediaItem() { + if (mediaItem == null) { + mediaItem = new MediaItem.Builder().setUri(uri).build(); + } + return mediaItem; + } + + } + public boolean isPlayerPrepared() { return player != null; } @@ -366,6 +1008,8 @@ public void onSeekProcessed(EventTime eventTime) { @Override public void onRenderedFirstFrame(EventTime eventTime, Object output, long renderTimeMs) { + fallbackPosition = C.TIME_UNSET; + fallbackDuration = C.TIME_UNSET; if (delegate != null) { delegate.onRenderedFirstFrame(eventTime); } @@ -481,10 +1125,16 @@ public void setPlayWhenReady(boolean playWhenReady) { } public long getDuration() { + if (fallbackDuration != C.TIME_UNSET) { + return fallbackDuration; + } return player != null ? player.getDuration() : 0; } public long getCurrentPosition() { + if (fallbackPosition != C.TIME_UNSET) { + return fallbackPosition; + } return player != null ? player.getCurrentPosition() : 0; } @@ -643,7 +1293,9 @@ public void onPlayerError(PlaybackException error) { if (player != null) { player.clearVideoTextureView(textureView); player.setVideoTextureView(textureView); - if (loopingMediaSource) { + if (videoQualities != null) { + preparePlayer(videoQualities, videoQualityToSelect); + } else if (loopingMediaSource) { preparePlayerLoop(videoUri, videoType, audioUri, audioType); } else { preparePlayer(videoUri, videoType); @@ -654,7 +1306,9 @@ public void onPlayerError(PlaybackException error) { } else { player.clearVideoTextureView(textureView); player.setVideoTextureView(textureView); - if (loopingMediaSource) { + if (videoQualities != null) { + preparePlayer(videoQualities, videoQualityToSelect); + } else if (loopingMediaSource) { preparePlayerLoop(videoUri, videoType, audioUri, audioType); } else { preparePlayer(videoUri, videoType); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java index 6546d2a277..6caca2f8cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java @@ -428,6 +428,7 @@ private boolean prepareForMoving(MotionEvent ev, boolean forward) { getParent().requestDisallowInterceptTouchEvent(true); maybeStartTracking = false; startedTracking = true; + onStartTracking(); startedTrackingX = (int) (ev.getX() + additionalOffset); if (tabsView != null) { tabsView.setEnabled(false); @@ -448,6 +449,10 @@ private boolean prepareForMoving(MotionEvent ev, boolean forward) { return true; } + public void onStartTracking() { + + } + public boolean onInterceptTouchEvent(MotionEvent ev) { if (tabsView != null && tabsView.isAnimatingIndicator()) { return false; @@ -484,6 +489,7 @@ public boolean onTouchEventInternal(MotionEvent ev) { } if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && checkTabsAnimationInProgress()) { startedTracking = true; + onStartTracking(); startedTrackingPointerId = ev.getPointerId(0); startedTrackingX = (int) ev.getX(); if (animatingForward) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java index ffcefc00dd..789402ba22 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java @@ -1,5 +1,7 @@ package org.telegram.ui.Components.spoilers; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; @@ -18,17 +20,13 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; -import android.graphics.text.LineBreaker; import android.os.Build; import android.text.Layout; -import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.StaticLayout; -import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.text.style.ReplacementSpan; -import android.util.Log; import android.view.View; import android.widget.TextView; @@ -46,10 +44,8 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.CachedStaticLayout; import org.telegram.ui.Cells.BaseCell; -import org.telegram.ui.Components.BlurredFrameLayout; import org.telegram.ui.Components.Easings; import org.telegram.ui.Components.QuoteSpan; -import org.telegram.ui.Components.Size; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.TextStyleSpan; @@ -722,11 +718,13 @@ public static void layoutDrawMaybe(Layout layout, Canvas canvas) { /** * Optimized version of text layout double-render - * @param v View to use as a parent view + * + * @param v View to use as a parent view * @param invalidateSpoilersParent Set to invalidate parent or not * @param spoilersColor Spoilers' color * @param verticalOffset Additional vertical offset * @param patchedLayoutRef Patched layout reference + * @param patchedLayoutType * @param textLayout Layout to render * @param spoilers Spoilers list to render * @param canvas Canvas to render @@ -734,8 +732,8 @@ public static void layoutDrawMaybe(Layout layout, Canvas canvas) { */ @SuppressLint("WrongConstant") @MainThread - public static void renderWithRipple(View v, boolean invalidateSpoilersParent, int spoilersColor, int verticalOffset, AtomicReference patchedLayoutRef, Layout textLayout, List spoilers, Canvas canvas, boolean useParentWidth) { - if (spoilers.isEmpty()) { + public static void renderWithRipple(View v, boolean invalidateSpoilersParent, int spoilersColor, int verticalOffset, AtomicReference patchedLayoutRef, int patchedLayoutType, Layout textLayout, List spoilers, Canvas canvas, boolean useParentWidth) { + if (spoilers == null || spoilers.isEmpty()) { layoutDrawMaybe(textLayout, canvas); return; } @@ -769,7 +767,9 @@ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, } Layout layout; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (patchedLayoutType == 1) { + layout = new StaticLayout(sb, textLayout.getPaint(), textLayout.getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, dp(1.66f), false); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { layout = StaticLayout.Builder.obtain(sb, 0, sb.length(), textLayout.getPaint(), textLayout.getWidth()) .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) @@ -826,7 +826,7 @@ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, eff.setInvalidateParent(invalidateSpoilersParent); if (eff.getParentView() != v) eff.setParentView(v); if (eff.shouldInvalidateColor()) { - eff.setColor(ColorUtils.blendARGB(spoilersColor, Theme.chat_msgTextPaint.getColor(), Math.max(0, eff.getRippleProgress()))); + eff.setColor(ColorUtils.blendARGB(spoilersColor, patchedLayoutType == 1 ? textLayout.getPaint().getColor() : Theme.chat_msgTextPaint.getColor(), Math.max(0, eff.getRippleProgress()))); } else { eff.setColor(spoilersColor); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java index 2cf09260f2..30f9e6853e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java @@ -145,20 +145,7 @@ public static void startCall(TLRPC.Chat chat, TLRPC.InputPeer peer, String hash, return; } - if (Build.VERSION.SDK_INT >= 23) { - ArrayList permissions = new ArrayList<>(); - ChatObject.Call call = accountInstance.getMessagesController().getGroupCall(chat.id, false); - if (activity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && !(call != null && call.call.rtmp_stream)) { - permissions.add(Manifest.permission.RECORD_AUDIO); - } - if (permissions.isEmpty()) { - initiateCall(null, chat, hash, false, false, createCall, checkJoiner, activity, fragment, accountInstance); - } else { - activity.requestPermissions(permissions.toArray(new String[0]), 103); - } - } else { - initiateCall(null, chat, hash, false, false, createCall, checkJoiner, activity, fragment, accountInstance); - } + initiateCall(null, chat, hash, false, false, createCall, checkJoiner, activity, fragment, accountInstance); } private static void initiateCall(TLRPC.User user, TLRPC.Chat chat, String hash, boolean videoCall, boolean canVideoCall, boolean createCall, Boolean checkJoiner, final Activity activity, BaseFragment fragment, AccountInstance accountInstance) { @@ -227,6 +214,10 @@ private static void initiateCall(TLRPC.User user, TLRPC.Chat chat, String hash, } private static void doInitiateCall(TLRPC.User user, TLRPC.Chat chat, String hash, TLRPC.InputPeer peer, boolean hasFewPeers, boolean videoCall, boolean canVideoCall, boolean createCall, Activity activity, BaseFragment fragment, AccountInstance accountInstance, boolean checkJoiner, boolean checkAnonymous) { + doInitiateCall(user, chat, hash, peer, hasFewPeers, videoCall, canVideoCall, createCall, activity, fragment, accountInstance,checkJoiner, checkAnonymous, false); + } + + private static void doInitiateCall(TLRPC.User user, TLRPC.Chat chat, String hash, TLRPC.InputPeer peer, boolean hasFewPeers, boolean videoCall, boolean canVideoCall, boolean createCall, Activity activity, BaseFragment fragment, AccountInstance accountInstance, boolean checkJoiner, boolean checkAnonymous, boolean isRtmpStream) { if (activity == null || user == null && chat == null) { return; } @@ -257,21 +248,21 @@ protected void onJoin() { } } if (checkJoiner && chat != null) { - JoinCallAlert.open(activity, -chat.id, accountInstance, fragment, createCall ? JoinCallAlert.TYPE_CREATE : JoinCallAlert.TYPE_JOIN, null, (selectedPeer, hasFew, schedule) -> { + JoinCallAlert.open(activity, -chat.id, accountInstance, fragment, createCall ? JoinCallAlert.TYPE_CREATE : JoinCallAlert.TYPE_JOIN, null, (selectedPeer, hasFew, schedule, rtmp) -> { if (createCall && schedule) { GroupCallActivity.create((LaunchActivity) activity, accountInstance, chat, selectedPeer, hasFew, hash); } else if (!hasFew && hash != null) { JoinCallByUrlAlert alert = new JoinCallByUrlAlert(activity, chat) { @Override protected void onJoin() { - doInitiateCall(user, chat, hash, selectedPeer, false, videoCall, canVideoCall, createCall, activity, fragment, accountInstance, false, true); + doInitiateCall(user, chat, hash, selectedPeer, false, videoCall, canVideoCall, createCall, activity, fragment, accountInstance, false, true, rtmp); } }; if (fragment != null) { fragment.showDialog(alert); } } else { - doInitiateCall(user, chat, hash, selectedPeer, hasFew, videoCall, canVideoCall, createCall, activity, fragment, accountInstance, false, true); + doInitiateCall(user, chat, hash, selectedPeer, hasFew, videoCall, canVideoCall, createCall, activity, fragment, accountInstance, false, true, rtmp); } }); return; @@ -321,6 +312,7 @@ protected void onJoin() { intent.putExtra("chat_id", chat.id); intent.putExtra("createGroupCall", createCall); intent.putExtra("hasFewPeers", hasFewPeers); + intent.putExtra("isRtmpStream", isRtmpStream); intent.putExtra("hash", hash); if (peer != null) { intent.putExtra("peerChannelId", peer.channel_id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index b28c50184c..42d5bf12bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -329,7 +329,7 @@ public void onSearchCollapse() { floatingButtonContainer.setTranslationY(AndroidUtilities.dp(100)); hideFloatingButton(false); } - if (sortItem != null) { + if (sortItem != null && !listViewAdapter.isEmpty) { sortItem.setVisibility(View.VISIBLE); } } @@ -401,6 +401,9 @@ public void notifyDataSetChanged() { listView.setFastScrollVisible(count != 0); } } + if (sortItem != null) { + sortItem.setVisibility(!isEmpty && !item.isSearchFieldVisible() ? View.VISIBLE : View.GONE); + } } }; listViewAdapter.setSortType(sortItem != null ? (sortByName ? 1 : 2) : 0, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 580e05391b..bc74f8cc22 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -12,6 +12,7 @@ import static org.telegram.messenger.LocaleController.formatPluralStringComma; import static org.telegram.messenger.LocaleController.formatString; import static org.telegram.messenger.LocaleController.getString; +import static org.telegram.ui.Components.AlertsCreator.createClearOrDeleteDialogsAlert; import android.Manifest; import android.animation.Animator; @@ -131,6 +132,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_chatlists; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -181,6 +183,7 @@ import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BlurredRecyclerView; import org.telegram.ui.Components.PermissionRequest; +import org.telegram.ui.Gifts.GiftSheet; import org.telegram.ui.Stars.StarsController; import org.telegram.ui.Stars.StarsIntroActivity; import org.telegram.ui.Stories.StealthModeAlert; @@ -242,6 +245,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -5361,7 +5365,9 @@ public void openAnimationFinished(boolean backward) { if (!hasFragment()) { invalidateScrollY = true; fixScrollYAfterArchiveOpened = true; - fragmentView.invalidate(); + if (fragmentView != null) { + fragmentView.invalidate(); + } } if (searchViewPager != null) { searchViewPager.updateTabs(); @@ -5547,7 +5553,7 @@ public boolean isStarsSubscriptionHintVisible() { } else { long starsNeeded = -c.balance; for (int i = 0; i < c.insufficientSubscriptions.size(); ++i) { - TLRPC.StarsSubscription sub = c.insufficientSubscriptions.get(i); + TL_stars.StarsSubscription sub = c.insufficientSubscriptions.get(i); TLRPC.Chat chat = getMessagesController().getChat(-DialogObject.getPeerDialogId(sub.peer)); if (chat == null) continue; starsNeeded += sub.pricing.amount; @@ -5846,7 +5852,7 @@ private void updateDialogsHint() { long starsNeeded = 0; if (c.hasInsufficientSubscriptions()) { for (int i = 0; i < c.insufficientSubscriptions.size(); ++i) { - TLRPC.StarsSubscription sub = c.insufficientSubscriptions.get(i); + TL_stars.StarsSubscription sub = c.insufficientSubscriptions.get(i); TLRPC.Chat chat = getMessagesController().getChat(-DialogObject.getPeerDialogId(sub.peer)); if (chat == null) continue; if (s.length() > 0) s.append(", "); @@ -5876,7 +5882,13 @@ private void updateDialogsHint() { dialogsHintCellVisible = true; dialogsHintCell.setVisibility(View.VISIBLE); dialogsHintCell.setCompact(true); - dialogsHintCell.setOnClickListener(v -> UserSelectorBottomSheet.open(0, state)); + dialogsHintCell.setOnClickListener(v -> { + if (state != null && state.today.size() == 1) { + showDialog(new GiftSheet(getContext(), currentAccount, state.today.get(0).id, null, null)); + return; + } + UserSelectorBottomSheet.open(0, state); + }); dialogsHintCell.setAvatars(currentAccount, users); dialogsHintCell.setText(Emoji.replaceWithRestrictedEmoji(AndroidUtilities.replaceSingleTag( users.size() == 1 ? @@ -5886,7 +5898,7 @@ private void updateDialogsHint() { AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, null ), dialogsHintCell.titleView, this::updateDialogsHint), - LocaleController.formatString(users.size() == 1 ? R.string.BirthdayTodaySingleMessage : R.string.BirthdayTodayMultipleMessage) + LocaleController.formatString(users.size() == 1 ? R.string.BirthdayTodaySingleMessage2 : R.string.BirthdayTodayMultipleMessage2) ); dialogsHintCell.setOnCloseListener(v -> { BirthdayController.getInstance(currentAccount).hide(); @@ -8147,7 +8159,12 @@ private void onItemClick(View view, int position, RecyclerListView.Adapter adapt rightSlidingDialogContainer.finishPreview(); } else { viewPages[0].listView.prepareSelectorForAnimation(); - TopicsFragment topicsFragment = new TopicsFragment(args); + TopicsFragment topicsFragment = new TopicsFragment(args) { + @Override + public boolean isRightFragment() { + return true; + } + }; topicsFragment.parentDialogsActivity = this; rightSlidingDialogContainer.presentFragment(getParentLayout(), topicsFragment); } @@ -8696,17 +8713,19 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { previewMenu[0].addView(muteItem); } - ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true); - deleteItem.setIconColor(getThemedColor(Theme.key_text_RedRegular)); - deleteItem.setTextColor(getThemedColor(Theme.key_text_RedBold)); - deleteItem.setSelectorColor(Theme.multAlpha(getThemedColor(Theme.key_text_RedBold), .12f)); - deleteItem.setTextAndIcon(LocaleController.getString(R.string.Delete), R.drawable.msg_delete); - deleteItem.setMinimumWidth(160); - deleteItem.setOnClickListener(e -> { - performSelectedDialogsAction(dialogIdArray, delete, false, false); - finishPreviewFragment(); - }); - previewMenu[0].addView(deleteItem); + if (dialogId != UserObject.VERIFY) { + ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true); + deleteItem.setIconColor(getThemedColor(Theme.key_text_RedRegular)); + deleteItem.setTextColor(getThemedColor(Theme.key_text_RedBold)); + deleteItem.setSelectorColor(Theme.multAlpha(getThemedColor(Theme.key_text_RedBold), .12f)); + deleteItem.setTextAndIcon(LocaleController.getString(R.string.Delete), R.drawable.msg_delete); + deleteItem.setMinimumWidth(160); + deleteItem.setOnClickListener(e -> { + performSelectedDialogsAction(dialogIdArray, delete, false, false); + finishPreviewFragment(); + }); + previewMenu[0].addView(deleteItem); + } if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { if (searchString != null) { @@ -9010,6 +9029,10 @@ private boolean isDialogPinned(TLRPC.Dialog dialog) { } private void performSelectedDialogsAction(ArrayList selectedDialogs, int action, boolean alert, boolean longPress) { + performSelectedDialogsAction(selectedDialogs, action, alert, longPress, null); + } + + private void performSelectedDialogsAction(ArrayList selectedDialogs, int action, boolean alert, boolean longPress, HashSet dialogsIdsToRevoke) { if (getParentActivity() == null) { return; } @@ -9110,53 +9133,60 @@ private void performSelectedDialogsAction(ArrayList selectedDialogs, int a return; } } else if ((action == delete || action == clear) && count > 1 && alert) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - if (action == delete) { - builder.setTitle(LocaleController.formatString("DeleteFewChatsTitle", R.string.DeleteFewChatsTitle, LocaleController.formatPluralString("ChatsSelected", count))); - builder.setMessage(LocaleController.getString(R.string.AreYouSureDeleteFewChats)); - } else { - if (canClearCacheCount != 0) { - builder.setTitle(LocaleController.formatString("ClearCacheFewChatsTitle", R.string.ClearCacheFewChatsTitle, LocaleController.formatPluralString("ChatsSelectedClearCache", count))); - builder.setMessage(LocaleController.getString(R.string.AreYouSureClearHistoryCacheFewChats)); - } else { - builder.setTitle(LocaleController.formatString("ClearFewChatsTitle", R.string.ClearFewChatsTitle, LocaleController.formatPluralString("ChatsSelectedClear", count))); - builder.setMessage(LocaleController.getString(R.string.AreYouSureClearHistoryFewChats)); - } - } - builder.setPositiveButton(action == delete ? LocaleController.getString(R.string.Delete) - : canClearCacheCount != 0 ? LocaleController.getString(R.string.ClearHistoryCache) - : LocaleController.getString(R.string.ClearHistory), (dialog1, which) -> { - if (selectedDialogs.isEmpty()) { - return; - } - ArrayList didsCopy = new ArrayList<>(selectedDialogs); - final UndoView undoView = getUndoView(); - if (undoView != null) { - undoView.showWithAction(didsCopy, action == delete ? UndoView.ACTION_DELETE_FEW : UndoView.ACTION_CLEAR_FEW, null, null, () -> { - if (action == delete) { - getMessagesController().setDialogsInTransaction(true); - performSelectedDialogsAction(didsCopy, action, false, false); - getMessagesController().setDialogsInTransaction(false); - getMessagesController().checkIfFolderEmpty(folderId); - if (folderId != 0 && getDialogsArray(currentAccount, viewPages[0].dialogsType, folderId, false).size() == 0) { - viewPages[0].listView.setEmptyView(null); - viewPages[0].progressView.setVisibility(View.INVISIBLE); - finishFragment(); + boolean hasDialogsToRevoke = false; + HashSet dialogsIdsPossibleToRevoke = new HashSet<>(); + boolean canRevokePmInbox = MessagesController.getInstance(currentAccount).canRevokePmInbox; + long revokeTimePmLimit = MessagesController.getInstance(currentAccount).revokeTimePmLimit; + if (action == delete && canRevokePmInbox && revokeTimePmLimit == 0x7fffffff) { + for (Long selectedDialog : selectedDialogs) { + if (DialogObject.isUserDialog(selectedDialog) || DialogObject.isEncryptedDialog(selectedDialog)) { + TLRPC.User user = null; + if (DialogObject.isEncryptedDialog(selectedDialog)) { + TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(selectedDialog)); + if (encryptedChat != null) { + user = getMessagesController().getUser(encryptedChat.user_id); } } else { - performSelectedDialogsAction(didsCopy, action, false, false); + user = getMessagesController().getUser(selectedDialog); + } + if (user != null) { + ArrayList dialogMessages = MessagesController.getInstance(currentAccount).dialogMessage.get(user.id); + boolean lastMessageIsJoined = dialogMessages != null && dialogMessages.size() == 1 && dialogMessages.get(0) != null && dialogMessages.get(0).messageOwner != null && (dialogMessages.get(0).messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || dialogMessages.get(0).messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp); + boolean canRevokeInbox = !user.bot && !UserObject.isDeleted(user) && user.id != getUserConfig().getClientUserId() && !lastMessageIsJoined; + if (canRevokeInbox) { + hasDialogsToRevoke = true; + dialogsIdsPossibleToRevoke.add(selectedDialog); + } } - }, null); + } } - hideActionMode(action == clear); - }); - builder.setNegativeButton(LocaleController.getString(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)); } + + createClearOrDeleteDialogsAlert(this, action == clear, action == delete, canClearCacheCount, count, hasDialogsToRevoke, param -> { + if (selectedDialogs.isEmpty()) { + return; + } + ArrayList didsCopy = new ArrayList<>(selectedDialogs); + final UndoView undoView = getUndoView(); + if (undoView != null) { + undoView.showWithAction(didsCopy, action == delete ? UndoView.ACTION_DELETE_FEW : UndoView.ACTION_CLEAR_FEW, null, null, () -> { + if (action == delete) { + getMessagesController().setDialogsInTransaction(true); + performSelectedDialogsAction(didsCopy, action, false, false, param ? dialogsIdsPossibleToRevoke : null); + getMessagesController().setDialogsInTransaction(false); + getMessagesController().checkIfFolderEmpty(folderId); + if (folderId != 0 && getDialogsArray(currentAccount, viewPages[0].dialogsType, folderId, false).size() == 0) { + viewPages[0].listView.setEmptyView(null); + viewPages[0].progressView.setVisibility(View.INVISIBLE); + finishFragment(); + } + } else { + performSelectedDialogsAction(didsCopy, action, false, false); + } + }, null); + } + hideActionMode(action == clear); + }, resourceProvider); return; } else if (action == block && alert) { TLRPC.User user; @@ -9321,7 +9351,8 @@ private void performSelectedDialogsAction(ArrayList selectedDialogs, int a if (action == clear && canClearCacheCount != 0) { getMessagesController().deleteDialog(selectedDialog, 2, false); } else { - performDeleteOrClearDialogAction(action, selectedDialog, chat, isBot, false); + boolean revoke = dialogsIdsToRevoke != null && dialogsIdsToRevoke.contains(selectedDialog); + performDeleteOrClearDialogAction(action, selectedDialog, chat, isBot, revoke); } } } @@ -9615,7 +9646,7 @@ private void updateCounters(boolean hide) { canArchiveCount++; } - if (!DialogObject.isUserDialog(selectedDialog) || selectedDialog == selfUserId) { + if (!DialogObject.isUserDialog(selectedDialog) || selectedDialog == selfUserId || selectedDialog == UserObject.VERIFY) { cantBlockCount++; } else { TLRPC.User user = getMessagesController().getUser(selectedDialog); @@ -9676,7 +9707,9 @@ private void updateCounters(boolean hide) { canPinCount++; } canClearHistoryCount++; - canDeleteCount++; + if (dialog.id != UserObject.VERIFY) { + canDeleteCount++; + } } } if (deleteItem != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Gifts/GiftSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Gifts/GiftSheet.java new file mode 100644 index 0000000000..e6dc441f2f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Gifts/GiftSheet.java @@ -0,0 +1,1295 @@ +package org.telegram.ui.Gifts; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.formatPluralString; +import static org.telegram.messenger.LocaleController.formatPluralStringComma; +import static org.telegram.messenger.LocaleController.getString; +import static org.telegram.ui.Stars.StarsIntroActivity.StarsTransactionView.getPlatformDrawable; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.CornerPathEffect; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.billingclient.api.BillingClient; +import com.android.billingclient.api.BillingFlowParams; +import com.android.billingclient.api.ProductDetails; +import com.android.billingclient.api.QueryProductDetailsParams; + +import org.telegram.messenger.AccountInstance; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BillingController; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +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.SvgHelper; +import org.telegram.messenger.UserConfig; +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.tgnet.tl.TL_stars; +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.AlertsCreator; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.ExtendedGridLayoutManager; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; +import org.telegram.ui.Components.Premium.PremiumLockIconView; +import org.telegram.ui.Components.Premium.StarParticlesView; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftSentBottomSheet; +import org.telegram.ui.Components.RLottieDrawable; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ScaleStateListAnimator; +import org.telegram.ui.Components.Text; +import org.telegram.ui.Components.UItem; +import org.telegram.ui.Components.UniversalAdapter; +import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; +import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stars.ExplainStarsSheet; +import org.telegram.ui.Stars.StarsController; +import org.telegram.ui.Stars.StarsIntroActivity; +import org.telegram.ui.Stars.StarsReactionsSheet; +import org.telegram.ui.Stories.recorder.HintView2; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.TreeSet; + +public class GiftSheet extends BottomSheetWithRecyclerListView implements NotificationCenter.NotificationCenterDelegate { + + private final int currentAccount; + private UniversalAdapter adapter; + private List options; + private final Runnable closeParentSheet; + + private final long dialogId; + private final String name; + + private final FrameLayout premiumHeaderView; + private final LinearLayout starsHeaderView; + private final ExtendedGridLayoutManager layoutManager; + private final DefaultItemAnimator itemAnimator; + + private final ArrayList premiumTiers = new ArrayList<>(); + + private final int TAB_ALL = 0; + private final int TAB_LIMITED = 1; + private final ArrayList tabs = new ArrayList<>(); + private int selectedTab; + + public GiftSheet(Context context, int currentAccount, long userId, Runnable closeParentSheet) { + this(context, currentAccount, userId, null, closeParentSheet); + } + + public GiftSheet(Context context, int currentAccount, long userId, List options, Runnable closeParentSheet) { + super(context, null, false, false, false, null); + + this.currentAccount = currentAccount; + this.dialogId = userId; + this.options = options; + this.closeParentSheet = closeParentSheet; + setBackgroundColor(Theme.getColor(Theme.key_dialogGiftsBackground)); + fixNavigationBar(Theme.getColor(Theme.key_dialogGiftsBackground)); + + StarsController.getInstance(currentAccount).loadStarGifts(); + + final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userId); + this.name = UserObject.getForcedFirstName((TLRPC.User) user); + topPadding = 0.15f; + + // Gift Premium header + premiumHeaderView = new FrameLayout(context); + + final FrameLayout topView = new FrameLayout(context); + topView.setClipChildren(false); + topView.setClipToPadding(false); + + final StarParticlesView particlesView = StarsIntroActivity.makeParticlesView(context, 70, 0); + topView.addView(particlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + final BackupImageView avatarImageView = new BackupImageView(context); + avatarImageView.setRoundRadius(dp(50)); + final AvatarDrawable avatarDrawable = new AvatarDrawable(); + avatarDrawable.setInfo(user); + avatarImageView.setForUserOrChat(user, avatarDrawable); + topView.addView(avatarImageView, LayoutHelper.createFrame(100, 100, Gravity.CENTER, 0, 32, 0, 24)); + + final LinearLayout bottomView = new LinearLayout(context); + bottomView.setOrientation(LinearLayout.VERTICAL); + + premiumHeaderView.addView(topView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 150)); + premiumHeaderView.addView(bottomView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.TOP, 0, 145, 0, 0)); + + final TextView titleView = new TextView(context); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTypeface(AndroidUtilities.bold()); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + titleView.setGravity(Gravity.CENTER); + bottomView.addView(titleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 4, 0, 4, 0)); + + final LinkSpanDrawable.LinksTextView subtitleView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + subtitleView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + subtitleView.setGravity(Gravity.CENTER); + bottomView.addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 4, 9, 4, 10)); + + titleView.setText(getString(R.string.Gift2Premium)); + subtitleView.setText(TextUtils.concat( + AndroidUtilities.replaceTags(LocaleController.formatString(R.string.Gift2PremiumInfo, name)), + " ", + AndroidUtilities.replaceArrows(AndroidUtilities.makeClickable(getString(R.string.Gift2PremiumInfoLink), () -> { + BaseFragment lastFragment = LaunchActivity.getLastFragment(); + if (lastFragment == null) { + return; + } + BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams(); + params.transitionFromLeft = true; + params.allowNestedScroll = false; + lastFragment.showAsSheet(new PremiumPreviewFragment("gifts"), params); + }), true) + )); + subtitleView.setMaxWidth(HintView2.cutInFancyHalf(subtitleView.getText(), subtitleView.getPaint())); + + // Gift Stars header + starsHeaderView = new LinearLayout(context); + starsHeaderView.setOrientation(LinearLayout.VERTICAL); + + final TextView titleStarsView = new TextView(context); + titleStarsView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleStarsView.setTypeface(AndroidUtilities.bold()); + titleStarsView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + titleStarsView.setGravity(Gravity.CENTER); + starsHeaderView.addView(titleStarsView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 4, 16, 4, 0)); + + final LinkSpanDrawable.LinksTextView subtitleStarsView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + subtitleStarsView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + subtitleStarsView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleStarsView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + subtitleStarsView.setGravity(Gravity.CENTER); + starsHeaderView.addView(subtitleStarsView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 4, 9, 4, 10)); + + titleStarsView.setText(getString(R.string.Gift2Stars)); + subtitleStarsView.setText(TextUtils.concat( + AndroidUtilities.replaceTags(LocaleController.formatString(R.string.Gift2StarsInfo, name)), + " ", + AndroidUtilities.replaceArrows(AndroidUtilities.makeClickable(getString(R.string.Gift2StarsInfoLink), () -> { + new ExplainStarsSheet(context).show(); + }), true) + )); + + layoutManager = new ExtendedGridLayoutManager(context, 3); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (adapter == null || position == 0) + return layoutManager.getSpanCount(); + final UItem item = adapter.getItem(position - 1); + if (item == null || item.spanCount == UItem.MAX_SPAN_COUNT) + return layoutManager.getSpanCount(); + return item.spanCount; + } + }); + recyclerListView.setPadding(dp(16), 0, dp(16), 0); +// recyclerListView.addItemDecoration(new RecyclerView.ItemDecoration() { +// @Override +// public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { +// int position = parent.getChildAdapterPosition(view); +// int spanIndex = layoutManager.getSpanSizeLookup().getSpanIndex(position, layoutManager.getSpanCount()); +// int spanSize = layoutManager.getSpanSizeLookup().getSpanSize(position); +// if (view instanceof Tabs) { +// outRect.left = 0; +// outRect.right = 0; +// } else { +// outRect.left = dp(spanIndex == 0 ? 16 : 0); +// outRect.right = dp(spanIndex + spanSize == layoutManager.getSpanCount() ? 16 : 0); +// } +// } +// }); + recyclerListView.setClipToPadding(false); + recyclerListView.setLayoutManager(layoutManager); + recyclerListView.setSelectorType(9); + recyclerListView.setSelectorDrawableColor(0); + itemAnimator = new DefaultItemAnimator() { + @Override + protected float animateByScale(View view) { + return .3f; + } + }; + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayIncrement(40); + recyclerListView.setItemAnimator(itemAnimator); + recyclerListView.setOnItemClickListener((view, position) -> { + final UItem item = adapter.getItem(position - 1); + if (item == null) return; + + if (item.instanceOf(GiftCell.Factory.class)) { + if (item.object instanceof GiftPremiumBottomSheet.GiftTier) { + final GiftPremiumBottomSheet.GiftTier premiumTier = (GiftPremiumBottomSheet.GiftTier) item.object; + new SendGiftSheet(context, currentAccount, premiumTier, dialogId, () -> { + if (closeParentSheet != null) { + closeParentSheet.run(); + } + dismiss(); + }).show(); + return; + } else if (item.object instanceof TL_stars.StarGift) { + final TL_stars.StarGift gift = (TL_stars.StarGift) item.object; + if (gift.sold_out) { + StarsIntroActivity.showSoldOutGiftSheet(context, currentAccount, gift, resourcesProvider); + return; + } + new SendGiftSheet(context, currentAccount, gift, dialogId, () -> { + if (closeParentSheet != null) { + closeParentSheet.run(); + } + dismiss(); + }).show(); + } + } + }); + + updatePremiumTiers(); + adapter.update(false); + updateTitle(); + + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starGiftsLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.userInfoDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starGiftSoldOut); + } + + private void onGiftSuccess(boolean fromGooglePlay) { + TLRPC.UserFull full = MessagesController.getInstance(currentAccount).getUserFull(dialogId); + final TLObject user = MessagesController.getInstance(currentAccount).getUserOrChat(dialogId); + if (full != null) { + if (user instanceof TLRPC.User) { + ((TLRPC.User) user).premium = true; + MessagesController.getInstance(currentAccount).putUser((TLRPC.User) user, true); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.userInfoDidLoad, ((TLRPC.User) user).id, full); + } + } + + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null && lastFragment.getParentActivity() instanceof LaunchActivity) { + List fragments = new ArrayList<>(((LaunchActivity) lastFragment.getParentActivity()).getActionBarLayout().getFragmentStack()); + + INavigationLayout layout = lastFragment.getParentLayout(); + ChatActivity lastChatActivity = null; + for (BaseFragment fragment : fragments) { + if (fragment instanceof ChatActivity) { + lastChatActivity = (ChatActivity) fragment; + if (lastChatActivity.getDialogId() != dialogId) { + fragment.removeSelfFromStack(); + } + } else if (fragment instanceof ProfileActivity) { + if (fromGooglePlay && layout.getLastFragment() == fragment) { + fragment.finishFragment(); + } else { + fragment.removeSelfFromStack(); + } + } + } + if (lastChatActivity == null || lastChatActivity.getDialogId() != dialogId) { + AndroidUtilities.runOnUIThread(() -> { + Bundle args = new Bundle(); + args.putLong("user_id", dialogId); + layout.presentFragment(new ChatActivity(args), true); + }, 200); + } + } + + dismiss(); + if (closeParentSheet != null) { + closeParentSheet.run(); + } + } + + @Override + public void dismiss() { + super.dismiss(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.starGiftsLoaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.starGiftSoldOut); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.billingProductDetailsUpdated) { + updatePremiumTiers(); + } else if (id == NotificationCenter.starGiftsLoaded) { + if (adapter != null) { + adapter.update(true); + } + } else if (id == NotificationCenter.userInfoDidLoad) { + if (!isShown()) return; + if (premiumTiers == null || premiumTiers.isEmpty()) { + updatePremiumTiers(); + if (adapter != null) { + adapter.update(true); + } + } + } else if (id == NotificationCenter.starGiftSoldOut) { + if (!isShown()) return; + final TL_stars.StarGift gift = (TL_stars.StarGift) args[0]; + BulletinFactory.of(container, resourcesProvider) + .createEmojiBulletin(gift.sticker, getString(R.string.Gift2SoldOutTitle), AndroidUtilities.replaceTags(formatPluralStringComma("Gift2SoldOut", gift.availability_total))) + .show(); + if (adapter != null) { + adapter.update(true); + } + } + } + + private void updatePremiumTiers() { + premiumTiers.clear(); +// TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); +// if (userFull != null) { +// List products = new ArrayList<>(); +// long pricePerMonthMax = 0; +// for (int i = userFull.premium_gifts.size() - 1; i >= 0; i--) { +// final TLRPC.TL_premiumGiftOption option = userFull.premium_gifts.get(i); +// GiftPremiumBottomSheet.GiftTier giftTier = new GiftPremiumBottomSheet.GiftTier(option); +// premiumTiers.add(giftTier); +// if (BuildVars.useInvoiceBilling()) { +// if (giftTier.getPricePerMonth() > pricePerMonthMax) { +// pricePerMonthMax = giftTier.getPricePerMonth(); +// } +// } else if (giftTier.getStoreProduct() != null && BillingController.getInstance().isReady()) { +// products.add(QueryProductDetailsParams.Product.newBuilder() +// .setProductType(BillingClient.ProductType.INAPP) +// .setProductId(giftTier.getStoreProduct()) +// .build()); +// } +// } +// if (BuildVars.useInvoiceBilling()) { +// for (GiftPremiumBottomSheet.GiftTier tier : premiumTiers) { +// tier.setPricePerMonthRegular(pricePerMonthMax); +// } +// } else if (!products.isEmpty()) { +// long startMs = System.currentTimeMillis(); +// BillingController.getInstance().queryProductDetails(products, (billingResult, list) -> { +// long pricePerMonthMaxStore = 0; +// +// for (ProductDetails details : list) { +// for (GiftPremiumBottomSheet.GiftTier giftTier : premiumTiers) { +// if (giftTier.getStoreProduct() != null && giftTier.getStoreProduct().equals(details.getProductId())) { +// giftTier.setGooglePlayProductDetails(details); +// +// if (giftTier.getPricePerMonth() > pricePerMonthMaxStore) { +// pricePerMonthMaxStore = giftTier.getPricePerMonth(); +// } +// break; +// } +// } +// } +// +// for (GiftPremiumBottomSheet.GiftTier giftTier : premiumTiers) { +// giftTier.setPricePerMonthRegular(pricePerMonthMaxStore); +// } +// AndroidUtilities.runOnUIThread(() -> { +// if (adapter != null) { +// adapter.update(false); +// } +// }); +// }); +// } +// } + if (premiumTiers.isEmpty() && options != null && !options.isEmpty()) { + List products = new ArrayList<>(); + long pricePerMonthMax = 0; + for (int i = options.size() - 1; i >= 0; i--) { + final TLRPC.TL_premiumGiftCodeOption option = options.get(i); + GiftPremiumBottomSheet.GiftTier giftTier = new GiftPremiumBottomSheet.GiftTier(option); + premiumTiers.add(giftTier); + if (BuildVars.useInvoiceBilling()) { + if (giftTier.getPricePerMonth() > pricePerMonthMax) { + pricePerMonthMax = giftTier.getPricePerMonth(); + } + } else if (giftTier.getStoreProduct() != null && BillingController.getInstance().isReady()) { + products.add(QueryProductDetailsParams.Product.newBuilder() + .setProductType(BillingClient.ProductType.INAPP) + .setProductId(giftTier.getStoreProduct()) + .build()); + } + } + if (BuildVars.useInvoiceBilling()) { + for (GiftPremiumBottomSheet.GiftTier tier : premiumTiers) { + tier.setPricePerMonthRegular(pricePerMonthMax); + } + } else if (!products.isEmpty()) { + long startMs = System.currentTimeMillis(); + BillingController.getInstance().queryProductDetails(products, (billingResult, list) -> { + long pricePerMonthMaxStore = 0; + + for (ProductDetails details : list) { + for (GiftPremiumBottomSheet.GiftTier giftTier : premiumTiers) { + if (giftTier.getStoreProduct() != null && giftTier.getStoreProduct().equals(details.getProductId())) { + giftTier.setGooglePlayProductDetails(details); + + if (giftTier.getPricePerMonth() > pricePerMonthMaxStore) { + pricePerMonthMaxStore = giftTier.getPricePerMonth(); + } + break; + } + } + } + + for (GiftPremiumBottomSheet.GiftTier giftTier : premiumTiers) { + giftTier.setPricePerMonthRegular(pricePerMonthMaxStore); + } + AndroidUtilities.runOnUIThread(() -> { + if (adapter != null) { + adapter.update(false); + } + }); + }); + } + } + if (premiumTiers.isEmpty()) { +// if (userFull == null) { +// TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); +// if (user != null) { +// MessagesController.getInstance(currentAccount).loadUserInfo(user, true, 0); +// } +// } + BoostRepository.loadGiftOptions(currentAccount, null, paymentOptions -> { + if (getContext() == null || !isShown()) return; + options = BoostRepository.filterGiftOptions(paymentOptions, 1); + options = BoostRepository.filterGiftOptionsByBilling(options); + if (!options.isEmpty()) { + updatePremiumTiers(); + if (adapter != null) { + adapter.update(true); + } + } + }); + } + } + + @Override + protected CharSequence getTitle() { + return LocaleController.formatString(R.string.Gift2User, name); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + adapter = new UniversalAdapter(recyclerListView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider); + adapter.setApplyBackground(false); + return adapter; + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + items.add(UItem.asCustom(premiumHeaderView)); + if (premiumTiers != null && !premiumTiers.isEmpty()) { + for (GiftPremiumBottomSheet.GiftTier tier : premiumTiers) { + items.add(GiftCell.Factory.asPremiumGift(tier)); + } + } else { + items.add(UItem.asFlicker(1, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + items.add(UItem.asFlicker(2, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + items.add(UItem.asFlicker(3, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + } + + final ArrayList gifts = StarsController.getInstance(currentAccount).gifts; + if (!MessagesController.getInstance(currentAccount).stargiftsBlocked && !gifts.isEmpty()) { + items.add(UItem.asCustom(starsHeaderView)); + final TreeSet prices = new TreeSet<>(); + for (int i = 0; i < gifts.size(); ++i) { + final TL_stars.StarGift gift = gifts.get(i); + prices.add(gift.stars); + } + + final ArrayList tabs = new ArrayList<>(); + tabs.add(getString(R.string.Gift2TabAll)); + tabs.add(getString(R.string.Gift2TabLimited)); + final Iterator priceIt = prices.iterator(); + final ArrayList pricesArray = new ArrayList<>(); + while (priceIt.hasNext()) { + final long price = priceIt.next(); + tabs.add(StarsIntroActivity.replaceStarsWithPlain("⭐️ " + LocaleController.formatNumber(price, ','), .8f)); + pricesArray.add(price); + } + items.add(Tabs.Factory.asTabs(1, tabs, selectedTab, tab -> { + if (selectedTab == tab) return; + selectedTab = tab; + itemAnimator.endAnimations(); + adapter.update(true); + })); + + final long selectedPrice = selectedTab - 2 >= 0 && selectedTab - 2 < pricesArray.size() ? pricesArray.get(selectedTab - 2) : 0; + for (int i = 0; i < gifts.size(); ++i) { + final TL_stars.StarGift gift = gifts.get(i); + if ( + selectedTab == TAB_ALL || + selectedTab == TAB_LIMITED && gift.limited || + selectedTab >= 2 && gift.stars == selectedPrice + ) { + items.add(GiftCell.Factory.asStarGift(selectedTab, gift)); + } + } + if (StarsController.getInstance(currentAccount).giftsLoading) { + items.add(UItem.asFlicker(4, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + items.add(UItem.asFlicker(5, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + items.add(UItem.asFlicker(6, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + } + items.add(UItem.asSpace(dp(40))); + } + } + + public static class GiftCell extends FrameLayout { + + private final int currentAccount; + private final Theme.ResourcesProvider resourcesProvider; + + private final FrameLayout card; + private final Ribbon ribbon; + private final AvatarDrawable avatarDrawable; + private final BackupImageView avatarView; + private final BackupImageView imageView; + private final PremiumLockIconView lockView; + + private final TextView titleView; + private final TextView subtitleView; + private final TextView priceView; + + private Runnable cancel; + + public GiftCell(Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { + super(context); + + this.currentAccount = currentAccount; + this.resourcesProvider = resourcesProvider; + + ScaleStateListAnimator.apply(this, .04f, 1.5f); + + card = new FrameLayout(context); + card.setBackground(new CardBackground(resourcesProvider)); + addView(card, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); + + ribbon = new Ribbon(context); + addView(ribbon, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP, 0, 2, 1, 0)); + + imageView = new BackupImageView(context); + imageView.getImageReceiver().setAutoRepeat(0); + card.addView(imageView, LayoutHelper.createFrame(100, 100, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 0)); + + lockView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_GIFT_LOCK, resourcesProvider); + lockView.setImageReceiver(imageView.getImageReceiver()); + card.addView(lockView, LayoutHelper.createFrame(30, 30, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 38, 0, 0)); + + titleView = new TextView(context); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + titleView.setGravity(Gravity.CENTER); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + titleView.setTypeface(AndroidUtilities.bold()); + card.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 0, 93, 0, 0)); + + subtitleView = new TextView(context); + subtitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + subtitleView.setGravity(Gravity.CENTER); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + card.addView(subtitleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 0, 111, 0, 0)); + + priceView = new TextView(context); + priceView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + priceView.setTypeface(AndroidUtilities.bold()); + priceView.setPadding(dp(10), 0, dp(10), 0); + priceView.setGravity(Gravity.CENTER); + priceView.setBackground(new StarsBackground()); + priceView.setTextColor(0xFF3391D4); + card.addView(priceView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 26, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 133, 0, 11)); + + avatarDrawable = new AvatarDrawable(); + avatarView = new BackupImageView(context); + avatarView.setRoundRadius(dp(20)); + avatarView.setVisibility(View.GONE); + card.addView(avatarView, LayoutHelper.createFrame(20, 20, Gravity.TOP | Gravity.LEFT, 2, 2, 2, 2)); + } + + private GiftPremiumBottomSheet.GiftTier lastTier; + + public void setPremiumGift(GiftPremiumBottomSheet.GiftTier tier) { + final int months = tier.getMonths(); + int type = months <= 3 ? 2 : months <= 6 ? 3 : 4; + if (lastTier != tier) { + cancel = StarsIntroActivity.setGiftImage(imageView, imageView.getImageReceiver(), type); + if (cancel != null) { + cancel.run(); + cancel = null; + } + } + titleView.setText(LocaleController.formatPluralString("Gift2Months", months)); + subtitleView.setText(getString(R.string.TelegramPremiumShort)); + titleView.setVisibility(View.VISIBLE); + subtitleView.setVisibility(View.VISIBLE); + imageView.setTranslationY(-dp(8)); + avatarView.setVisibility(View.GONE); + lockView.setVisibility(View.GONE); + + if (tier.getDiscount() > 0) { + ribbon.setVisibility(View.VISIBLE); + ribbon.setColor(0xFFF55951); + ribbon.setText(12, LocaleController.formatString(R.string.GiftPremiumOptionDiscount, tier.getDiscount()), true); + } else { + ribbon.setVisibility(View.GONE); + } + + priceView.setPadding(dp(10), 0, dp(10), 0); + priceView.setText(tier.getFormattedPrice()); + priceView.setBackground(Theme.createRoundRectDrawable(dp(13), 0x193391D4)); + priceView.setTextColor(0xFF3391D4); + ((MarginLayoutParams) priceView.getLayoutParams()).topMargin = dp(133); + + lastTier = tier; + lastDocument = null; + } + + private TLRPC.Document lastDocument; + private void setSticker(TLRPC.Document document, Object parentObject) { + if (document == null) { + imageView.clearImage(); + lastDocument = null; + return; + } + + if (lastDocument == document) return; + lastDocument = document; + + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, dp(100)); + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.3f); + + imageView.setImage( + ImageLocation.getForDocument(document), "100_100", + ImageLocation.getForDocument(photoSize, document), "100_100", + svgThumb, + parentObject + ); + } + + public void setStarsGift(TL_stars.StarGift gift) { + if (cancel != null) { + cancel.run(); + cancel = null; + } + + setSticker(gift.sticker, gift); + titleView.setVisibility(View.GONE); + subtitleView.setVisibility(View.GONE); + imageView.setTranslationY(0); + lockView.setVisibility(View.GONE); + + if (gift.limited && gift.availability_remains <= 0) { + ribbon.setVisibility(View.VISIBLE); + ribbon.setColor(Theme.getColor(Theme.key_text_RedBold, resourcesProvider)); + ribbon.setText(LocaleController.getString(R.string.Gift2SoldOut), true); + } else if (gift.limited) { + ribbon.setVisibility(View.VISIBLE); + ribbon.setColor(0xFF46A4F2); + ribbon.setText(getString(R.string.Gift2LimitedRibbon), false); + } else { + ribbon.setVisibility(View.GONE); + } + + avatarView.setVisibility(View.GONE); + + priceView.setPadding(dp(8), 0, dp(10), 0); + priceView.setText(StarsIntroActivity.replaceStarsWithPlain("XTR " + LocaleController.formatNumber(gift.stars, ','), .71f)); + priceView.setBackground(new StarsBackground()); + priceView.setTextColor(0xFFBF7600); + ((MarginLayoutParams) priceView.getLayoutParams()).topMargin = dp(103); + + lastTier = null; + } + + private TL_stars.UserStarGift lastUserGift; + + public void setStarsGift(TL_stars.UserStarGift userGift) { + if (cancel != null) { + cancel.run(); + cancel = null; + } + + setSticker(userGift.gift.sticker, userGift); + titleView.setVisibility(View.GONE); + subtitleView.setVisibility(View.GONE); + imageView.setTranslationY(0); + lockView.setWaitingImage(); + + lockView.setVisibility(View.VISIBLE); + if (lastUserGift == userGift) { + lockView.animate() + .alpha(userGift.unsaved ? 1f : 0f) + .scaleX(userGift.unsaved ? 1f : .4f) + .scaleY(userGift.unsaved ? 1f : .4f) + .setDuration(350) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .start(); + } else { + lockView.setAlpha(userGift.unsaved ? 1f : 0f); + lockView.setScaleX(userGift.unsaved ? 1f : 0.4f); + lockView.setScaleY(userGift.unsaved ? 1f : 0.4f); + } + + if (userGift.gift.limited) { + ribbon.setVisibility(View.VISIBLE); + ribbon.setColor(0xFF46A4F2); + ribbon.setText(LocaleController.formatString(R.string.Gift2Limited1OfRibbon, AndroidUtilities.formatWholeNumber(userGift.gift.availability_total, 0)), true); + } else { + ribbon.setVisibility(View.GONE); + } + + if (userGift.name_hidden) { + avatarView.setVisibility(View.VISIBLE); + CombinedDrawable iconDrawable = getPlatformDrawable("anonymous"); + iconDrawable.setIconSize(dp(16), dp(16)); + avatarView.setImageDrawable(iconDrawable); + } else { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userGift.from_id); + if (user != null) { + avatarView.setVisibility(View.VISIBLE); + avatarDrawable.setInfo(user); + avatarView.setForUserOrChat(user, avatarDrawable); + } else { + avatarView.setVisibility(View.GONE); + } + } + + priceView.setPadding(dp(8), 0, dp(10), 0); + priceView.setText(StarsIntroActivity.replaceStarsWithPlain("XTR " + LocaleController.formatNumber(Math.max(userGift.gift.stars, userGift.convert_stars > 0 ? userGift.convert_stars : userGift.gift.convert_stars), ','), .66f)); + priceView.setBackground(new StarsBackground()); + priceView.setTextColor(0xFFBF7600); + ((MarginLayoutParams) priceView.getLayoutParams()).topMargin = dp(103); + + lastUserGift = userGift; + lastTier = null; + } + + public static class Factory extends UItem.UItemFactory { + static { setup(new Factory()); } + + @Override + public GiftCell createView(Context context, int currentAccount, int classGuid, Theme.ResourcesProvider resourcesProvider) { + return new GiftCell(context, currentAccount, resourcesProvider); + } + + @Override + public void bindView(View view, UItem item, boolean divider) { + if (item.object instanceof GiftPremiumBottomSheet.GiftTier) { + ((GiftCell) view).setPremiumGift((GiftPremiumBottomSheet.GiftTier) item.object); + } else if (item.object instanceof TL_stars.StarGift) { + TL_stars.StarGift gift = (TL_stars.StarGift) item.object; + ((GiftCell) view).setStarsGift(gift); + } else if (item.object instanceof TL_stars.UserStarGift) { + TL_stars.UserStarGift gift = (TL_stars.UserStarGift) item.object; + ((GiftCell) view).setStarsGift(gift); + } + } + + public static UItem asPremiumGift(GiftPremiumBottomSheet.GiftTier tier) { + final UItem item = UItem.ofFactory(Factory.class).setSpanCount(1); + item.object = tier; + return item; + } + + public static UItem asStarGift(int tab, TL_stars.StarGift gift) { + final UItem item = UItem.ofFactory(Factory.class).setSpanCount(1); + item.intValue = tab; + item.object = gift; + return item; + } + + public static UItem asStarGift(int tab, TL_stars.UserStarGift gift) { + final UItem item = UItem.ofFactory(Factory.class).setSpanCount(1); + item.intValue = tab; + item.object = gift; + return item; + } + + @Override + public boolean equals(UItem a, UItem b) { + if (a.object != null || b.object != null) { + if (a.object instanceof GiftPremiumBottomSheet.GiftTier) { + return a.object == b.object; + } else if (a.object instanceof TL_stars.StarGift && b.object instanceof TL_stars.StarGift) { + final TL_stars.StarGift ag = (TL_stars.StarGift) a.object; + final TL_stars.StarGift bg = (TL_stars.StarGift) b.object; + return ag.id == bg.id; + } else if (a.object instanceof TL_stars.UserStarGift && b.object instanceof TL_stars.UserStarGift) { + final TL_stars.UserStarGift ag = (TL_stars.UserStarGift) a.object; + final TL_stars.UserStarGift bg = (TL_stars.UserStarGift) b.object; + return ag.gift.id == bg.gift.id; + } + } + return ( + a.intValue == b.intValue && + a.checked == b.checked && + a.longValue == b.longValue && + TextUtils.equals(a.text, b.text) + ); + } + } + } + + public static class Ribbon extends View { + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Path path = new Path(); + private Text text; + + public Ribbon(Context context) { + super(context); + + paint.setColor(0xFFF55951); + paint.setPathEffect(new CornerPathEffect(dp(2.33f))); + } + + public void setColor(int color) { + paint.setColor(color); + } + + public void setText(CharSequence text, boolean bold) { + setText(bold ? 10 : 11, text, bold); + } + + public void setText(int textSizeDp, CharSequence text, boolean bold) { + this.text = new Text(text, textSizeDp, bold ? AndroidUtilities.bold() : null); + invalidate(); + } + + public static void fillRibbonPath(Path path, float s) { + path.rewind(); + path.moveTo(dp(s * 46.83f), dp(s * 24.5f)); + path.lineTo(dp(s * 23.5f), dp(s * 1.17f)); + path.cubicTo(dp(s * 22.75f), dp(s * 0.42f), dp(s * 21.73f), 0f, dp(s * 20.68f), 0f); + path.cubicTo(dp(s * 19.62f), 0f, dp(s * 2.73f), dp(s * 0.05f), dp(s * 1.55f), dp(s * 0.05f)); + path.cubicTo(dp(s * 0.36f), dp(s * 0.05f), dp(s * -0.23f), dp(s * 1.4885f), dp(s * 0.6f), dp(s * 2.32f)); + path.lineTo(dp(s * 45.72f), dp(s * 47.44f)); + path.cubicTo(dp(s * 46.56f), dp(s * 48.28f), dp(s * 48f), dp(s * 47.68f), dp(s * 48f), dp(s * 46.5f)); + path.cubicTo(dp(s * 48f), dp(s * 45.31f), dp(s * 48f), dp(s * 28.38f), dp(s * 48f), dp(s * 27.32f)); + path.cubicTo(dp(s * 48f), dp(s * 26.26f), dp(s * 47.5f), dp(s * 25.24f), dp(s * 46.82f), dp(s * 24.5f)); + path.close(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + fillRibbonPath(path, 1f); + setMeasuredDimension(dp(48), dp(48)); + } + + @Override + protected void dispatchDraw(@NonNull Canvas canvas) { + canvas.drawPath(path, paint); + if (text != null) { + canvas.save(); + canvas.rotate(45, getWidth() / 2f + dp(6), getHeight() / 2f - dp(6)); + final float scale = Math.min(1, dp(40) / text.getCurrentWidth()); + canvas.scale(scale, scale, getWidth() / 2f + dp(6), getHeight() / 2f - dp(6)); + text.draw(canvas, getWidth() / 2f + dp(6) - text.getWidth() / 2f, getHeight() / 2f - dp(5), 0xFFFFFFFF, 1f); + canvas.restore(); + } + } + } + + public static class StarsBackground extends Drawable { + + public final RectF rectF = new RectF(); + public final Path path = new Path(); + public final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); { backgroundPaint.setColor(0x40E8AB02); } + public final StarsReactionsSheet.Particles particles = new StarsReactionsSheet.Particles(StarsReactionsSheet.Particles.TYPE_RADIAL, 25); + + @Override + public void draw(@NonNull Canvas canvas) { + final float r = Math.min(getBounds().width(), getBounds().height()) / 2f; + rectF.set(getBounds()); + path.rewind(); + path.addRoundRect(rectF, r, r, Path.Direction.CW); + canvas.drawPath(path, backgroundPaint); + canvas.save(); + canvas.clipPath(path); + particles.setBounds(rectF); + particles.process(); + particles.draw(canvas, 0xFFF0981D); + canvas.restore(); + invalidateSelf(); + } + + @Override + public void setAlpha(int alpha) { + backgroundPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + backgroundPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + } + + public TLRPC.Document getStarGiftDocument(String emoji) { + TLRPC.TL_messages_stickerSet set; + TLRPC.Document document = null; + + final String packName = "RestrictedEmoji"; + set = MediaDataController.getInstance(currentAccount).getStickerSetByName(packName); + if (set == null) { + set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(packName); + } + if (set != null) { + for (int i = 0; i < set.packs.size(); ++i) { + TLRPC.TL_stickerPack pack = set.packs.get(i); + if (TextUtils.equals(pack.emoticon, emoji) && !pack.documents.isEmpty()) { + long documentId = pack.documents.get(0); + for (int j = 0; j < set.documents.size(); ++j) { + TLRPC.Document d = set.documents.get(j); + if (d != null && d.id == documentId) { + document = d; + break; + } + } + break; + } + } + if (document == null && !set.documents.isEmpty()) { + document = set.documents.get(0); + } + } + return document; + } + + public static Runnable setStarGiftImage(View view, ImageReceiver imageReceiver, String emoji) { + final boolean[] played = new boolean[1]; + final int currentAccount = imageReceiver.getCurrentAccount(); + Runnable setImage = () -> { + TLRPC.TL_messages_stickerSet set; + TLRPC.Document document = null; + + final String packName = "RestrictedEmoji"; + set = MediaDataController.getInstance(currentAccount).getStickerSetByName(packName); + if (set == null) { + set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(packName); + } + if (set != null) { + for (int i = 0; i < set.packs.size(); ++i) { + TLRPC.TL_stickerPack pack = set.packs.get(i); + if (TextUtils.equals(pack.emoticon, emoji) && !pack.documents.isEmpty()) { + long documentId = pack.documents.get(0); + for (int j = 0; j < set.documents.size(); ++j) { + TLRPC.Document d = set.documents.get(j); + if (d != null && d.id == documentId) { + document = d; + break; + } + } + break; + } + } + if (document == null && !set.documents.isEmpty()) { + document = set.documents.get(0); + } + } + + if (document != null) { + imageReceiver.setAllowStartLottieAnimation(true); + imageReceiver.setDelegate(new ImageReceiver.ImageReceiverDelegate() { + @Override + public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb, boolean memCache) { + if (set) { + RLottieDrawable drawable = imageReceiver.getLottieAnimation(); + if (drawable != null && !played[0]) { + drawable.setCurrentFrame(0, false); + AndroidUtilities.runOnUIThread(drawable::restart); + played[0] = true; + } + } + } + }); + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.3f); + imageReceiver.setAutoRepeat(0); + imageReceiver.setImage(ImageLocation.getForDocument(document), String.format(Locale.US, "%d_%d_nr", 160, 160), svgThumb, "tgs", set, 1); + } else { + MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, set == null); + } + }; + setImage.run(); + final Runnable cancel1 = NotificationCenter.getInstance(currentAccount).listen(view, NotificationCenter.didUpdatePremiumGiftStickers, args -> setImage.run()); + final Runnable cancel2 = NotificationCenter.getInstance(currentAccount).listen(view, NotificationCenter.diceStickersDidLoad, args -> setImage.run()); + return () -> { + cancel1.run(); + cancel2.run(); + }; + } + + public static class CardBackground extends Drawable { + + public final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final RectF rect = new RectF(); + + public CardBackground(Theme.ResourcesProvider resourcesProvider) { + paint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + paint.setShadowLayer(dp(2.66f), 0, dp(1.66f), Theme.getColor(Theme.key_dialogCardShadow, resourcesProvider)); + } + + @Override + public void draw(@NonNull Canvas canvas) { + Rect bounds = getBounds(); + rect.set(bounds); + rect.inset(dp(3.33f), dp(4)); + canvas.drawRoundRect(rect, dp(11), dp(11), paint); + } + + @Override + public boolean getPadding(@NonNull Rect padding) { + padding.set( + dp(3.33f), + dp(4), + dp(3.33f), + dp(4) + ); + return true; + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + } + + public static class Tabs extends HorizontalScrollView { + + private final Theme.ResourcesProvider resourcesProvider; + + private final LinearLayout layout; + private int selected; + private AnimatedFloat animatedSelected; + private final ArrayList tabs = new ArrayList<>(); + + private final RectF flooredRect = new RectF(), ceiledRect = new RectF(); + private final RectF selectedRect = new RectF(); + private final Paint selectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + public Tabs(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + + this.resourcesProvider = resourcesProvider; + + layout = new LinearLayout(context) { + @Override + protected void dispatchDraw(@NonNull Canvas canvas) { + selectedPaint.setColor(Theme.multAlpha(Theme.getColor(Theme.key_dialogGiftsTabText), .1f)); + final float selected = animatedSelected.set(Tabs.this.selected); + + int flooredIndex = Utilities.clamp((int) Math.floor(selected), tabs.size() - 1, 0); + int ceiledIndex = Utilities.clamp((int) Math.ceil(selected), tabs.size() - 1, 0); + if (flooredIndex < tabs.size()) { + setBounds(flooredRect, tabs.get(flooredIndex)); + } else if (ceiledIndex < tabs.size()) { + setBounds(flooredRect, tabs.get(ceiledIndex)); + } else { + flooredRect.set(0,0,0,0); + } + if (ceiledIndex < tabs.size()) { + setBounds(ceiledRect, tabs.get(ceiledIndex)); + } else if (flooredIndex < tabs.size()) { + setBounds(ceiledRect, tabs.get(flooredIndex)); + } else { + ceiledRect.set(0,0,0,0); + } + AndroidUtilities.lerp(flooredRect, ceiledRect, selected - flooredIndex, selectedRect); + + final float r = selectedRect.height() / 2f; + canvas.drawRoundRect(selectedRect, r, r, selectedPaint); + + super.dispatchDraw(canvas); + } + + private final void setBounds(RectF rect, View view) { + rect.set(view.getLeft() + dp(5), view.getTop(), view.getRight() - dp(5), view.getBottom()); + } + }; + layout.setOrientation(LinearLayout.HORIZONTAL); + layout.setPadding(0, dp(8), 0, dp(12)); + addView(layout); + + setHorizontalScrollBarEnabled(false); + + animatedSelected = new AnimatedFloat(layout, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + } + + private int lastId = Integer.MIN_VALUE; + public void set(int id, ArrayList tabs, int selected, Utilities.Callback whenTabSelected) { + final boolean animated = lastId == id; + lastId = id; + + if (this.tabs.size() != tabs.size()) { + int a = 0; + for (int i = 0; i < this.tabs.size(); ++i) { + CharSequence tabText = a < tabs.size() ? tabs.get(a) : null; + if (tabText == null) { + layout.removeView(this.tabs.remove(i)); + i--; + } else { + this.tabs.get(i).setText(tabText); + } + a++; + } + for (; a < tabs.size(); ++a) { + final TextView tab = new TextView(getContext()); + tab.setGravity(Gravity.CENTER); + tab.setText(tabs.get(a)); + tab.setTypeface(AndroidUtilities.bold()); + tab.setTextColor(Theme.blendOver(Theme.getColor(Theme.key_dialogGiftsBackground), Theme.getColor(Theme.key_dialogGiftsTabText))); + tab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + tab.setPadding(dp(16), 0, dp(16), 0); + ScaleStateListAnimator.apply(tab, 0.075f, 1.4f); + layout.addView(tab, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 26)); + this.tabs.add(tab); + } + } + + this.selected = selected; + if (!animated) { + animatedSelected.set(selected, true); + } + layout.invalidate(); + + for (int i = 0; i < this.tabs.size(); ++i) { + final int tabIndex = i; + this.tabs.get(i).setOnClickListener(v -> { + TextView tab = this.tabs.get(tabIndex); + smoothScrollTo(tab.getLeft() - tab.getWidth() / 2, 0); + if (whenTabSelected != null) { + whenTabSelected.run(tabIndex); + } + }); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + heightMeasureSpec + ); + } + + public static class Factory extends UItem.UItemFactory { + static { setup(new Factory()); } + + @Override + public Tabs createView(Context context, int currentAccount, int classGuid, Theme.ResourcesProvider resourcesProvider) { + return new Tabs(context, resourcesProvider); + } + + @Override + public void bindView(View view, UItem item, boolean divider) { + ((Tabs) view).set(item.id, (ArrayList) item.object, item.intValue, (Utilities.Callback) item.object2); + } + + public static UItem asTabs(int id, ArrayList tabs, int selected, Utilities.Callback whenTabSelected) { + final UItem item = UItem.ofFactory(Factory.class); + item.id = id; + item.object = tabs; + item.intValue = selected; + item.object2 = whenTabSelected; + return item; + } + + private static boolean eq(ArrayList a, ArrayList b) { + if (a == b) return true; + if (a == null && b == null) return true; + if (a == null || b == null) return false; + if (a.size() != b.size()) return false; + for (int i = 0; i < a.size(); ++i) { + if (!TextUtils.equals(a.get(i), b.get(i))) + return false; + } + return true; + } + + @Override + public boolean equals(UItem a, UItem b) { + return ( + a.id == b.id && + eq((ArrayList) a.object, (ArrayList) b.object) + ); + } + + @Override + public boolean contentsEquals(UItem a, UItem b) { + return a.intValue == b.intValue && a.object2 == b.object2 && equals(a, b); + } + } + + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Gifts/ProfileGiftsContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Gifts/ProfileGiftsContainer.java new file mode 100644 index 0000000000..8a88a88c3b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Gifts/ProfileGiftsContainer.java @@ -0,0 +1,314 @@ +package org.telegram.ui.Gifts; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.MessagesController.getInstance; + +import android.content.Context; +import android.graphics.Paint; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import org.checkerframework.checker.units.qual.A; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BirthdayController; +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.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.Premium.boosts.UserSelectorBottomSheet; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.UItem; +import org.telegram.ui.Components.UniversalAdapter; +import org.telegram.ui.Components.UniversalRecyclerView; +import org.telegram.ui.Stars.StarsController; +import org.telegram.ui.Stars.StarsIntroActivity; +import org.telegram.ui.Stories.bots.BotPreviewsEditContainer; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +public class ProfileGiftsContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + + private final int currentAccount; + private final long userId; + private final StarsController.GiftsList list; + private final Theme.ResourcesProvider resourcesProvider; + + private final UniversalRecyclerView listView; + private final FrameLayout buttonContainer; + private final ButtonWithCounterView button; + + private long getRandomUserId() { + final ConcurrentHashMap map = MessagesController.getInstance(currentAccount).getUsers(); + final int size = map.size(); + if (size == 0) { + return 0; + } + final int randomIndex = Utilities.fastRandom.nextInt(size); + int currentIndex = 0; + for (Map.Entry entry : map.entrySet()) { + if (currentIndex == randomIndex) { + return entry.getValue().id; + } + currentIndex++; + } + return 0; + } + + public ProfileGiftsContainer(Context context, int currentAccount, long userId, Theme.ResourcesProvider resourcesProvider) { + super(context); + + this.currentAccount = currentAccount; + this.userId = userId; + this.list = StarsController.getInstance(currentAccount).getProfileGiftsList(userId); + this.list.shown = true; + this.list.load(); + this.resourcesProvider = resourcesProvider; + + setBackgroundColor(Theme.blendOver( + Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider), + Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider), 0.04f) + )); + + listView = new UniversalRecyclerView(context, currentAccount, 0, false, this::fillItems, this::onItemClick, this::onItemLongPress, resourcesProvider, 3); + listView.adapter.setApplyBackground(false); + listView.setSelectorType(9); + listView.setSelectorDrawableColor(0); + listView.setPadding(dp(9), 0, dp(9), 0); + addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); + listView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + if (!listView.canScrollVertically(1) || isLoadingVisible()) { + list.load(); + } + } + }); + + buttonContainer = new FrameLayout(context); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.BOTTOM)); + + final View buttonShadow = new View(context); + buttonShadow.setBackgroundColor(Theme.getColor(Theme.key_dialogGrayLine, resourcesProvider)); + buttonContainer.addView(buttonShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1f / AndroidUtilities.density, Gravity.FILL_HORIZONTAL | Gravity.TOP)); + + button = new ButtonWithCounterView(context, resourcesProvider); + final SpannableStringBuilder sb = new SpannableStringBuilder("G " + LocaleController.getString(R.string.ProfileGiftsSend)); + final ColoredImageSpan span = new ColoredImageSpan(R.drawable.filled_gift_premium); + sb.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + button.setText(sb, false); + buttonContainer.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 10, 10 + 1f / AndroidUtilities.density, 10, 10)); + button.setOnClickListener(v -> { + UserSelectorBottomSheet.open(UserSelectorBottomSheet.TYPE_STAR_GIFT, 0, BirthdayController.getInstance(currentAccount).getState()); + }); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.starUserGiftsLoaded) { + if ((Long) args[0] == userId) { + if (listView != null && listView.adapter != null) { + listView.adapter.update(true); + } + if (!listView.canScrollVertically(1) || isLoadingVisible()) { + list.load(); + } + } + } + } + + private boolean isLoadingVisible() { + for (int i = 0; i < listView.getChildCount(); ++i) { + if (listView.getChildAt(i) instanceof FlickerLoadingView) + return true; + } + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starUserGiftsLoaded); + if (listView != null && listView.adapter != null) { + listView.adapter.update(false); + } + if (list != null) { + list.shown = true; + list.load(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.starUserGiftsLoaded); + if (list != null) { + list.shown = false; + } + } + + public int getGiftsCount() { + if (list != null && list.totalCount > 0) return list.totalCount; + final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(userId); + return userFull != null ? userFull.stargifts_count : 0; + } + + public CharSequence getLastEmojis(Paint.FontMetricsInt fontMetricsInt) { + if (list == null || list.gifts.isEmpty()) return ""; + + final HashSet giftsIds = new HashSet<>(); + final ArrayList gifts = new ArrayList<>(); + for (int i = 0; gifts.size() < 3 && i < list.gifts.size(); ++i) { + final TL_stars.UserStarGift gift = list.gifts.get(i); + if (giftsIds.contains(gift.gift.sticker.id)) continue; + giftsIds.add(gift.gift.sticker.id); + gifts.add(gift.gift.sticker); + } + + if (gifts.isEmpty()) return ""; + SpannableStringBuilder ssb = new SpannableStringBuilder(" "); + for (int i = 0; i < gifts.size(); ++i) { + SpannableStringBuilder emoji = new SpannableStringBuilder("x"); + emoji.setSpan(new AnimatedEmojiSpan(gifts.get(i), .9f, fontMetricsInt), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append(emoji); + } + return ssb; + } + + public long getLastEmojisHash() { + if (list == null || list.gifts.isEmpty()) return 0; + + long hash = 0; + int giftsCount = 0; + final HashSet giftsIds = new HashSet<>(); + for (int i = 0; giftsCount < 3 && i < list.gifts.size(); ++i) { + final TL_stars.UserStarGift gift = list.gifts.get(i); + if (giftsIds.contains(gift.gift.sticker.id)) continue; + giftsIds.add(gift.gift.sticker.id); + hash = Objects.hash(hash, gift.gift.sticker.id); + giftsCount++; + } + + return hash; + } + + private int visibleHeight = AndroidUtilities.displaySize.y; + public void setVisibleHeight(int height) { + visibleHeight = height; + buttonContainer.setTranslationY(-buttonContainer.getTop() + height - dp(48 + 10 + 10 + 1f / AndroidUtilities.density)); + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + final int spanCount = Math.max(1, list == null || list.totalCount == 0 ? 3 : Math.min(3, list.totalCount)); + if (listView != null) { + listView.setSpanCount(spanCount); + } + items.add(UItem.asSpace(dp(12))); + if (list != null) { + int spanCountLeft = 3; + for (TL_stars.UserStarGift userGift : list.gifts) { + items.add(GiftSheet.GiftCell.Factory.asStarGift(0, userGift)); + spanCountLeft--; + if (spanCountLeft == 0) { + spanCountLeft = 3; + } + } + if (list.loading || !list.endReached) { + for (int i = 0; i < (spanCountLeft <= 0 ? 3 : spanCountLeft); ++i) { + items.add(UItem.asFlicker(i, FlickerLoadingView.STAR_GIFT).setSpanCount(1)); + } + } + } + items.add(UItem.asSpace(dp(20))); + if (userId == UserConfig.getInstance(currentAccount).getClientUserId()) { + items.add(TextFactory.asText(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider), Gravity.CENTER, 14, LocaleController.getString(R.string.ProfileGiftsInfo), true, dp(24))); + } + items.add(UItem.asSpace(dp(24 + 48 + 10))); + } + + public void onItemClick(UItem item, View view, int position, float x, float y) { + if (item.object instanceof TL_stars.UserStarGift) { + final TL_stars.UserStarGift userGift = (TL_stars.UserStarGift) item.object; + StarsIntroActivity.showGiftSheet(getContext(), currentAccount, userId, userId == UserConfig.getInstance(currentAccount).getClientUserId(), userGift, resourcesProvider); + } + } + + public boolean onItemLongPress(UItem item, View view, int position, float x, float y) { + return false; + } + + public RecyclerListView getCurrentListView() { + return listView; + } + + public static class TextFactory extends UItem.UItemFactory { + static { setup(new TextFactory()); } + + @Override + public LinkSpanDrawable.LinksTextView createView(Context context, int currentAccount, int classGuid, Theme.ResourcesProvider resourcesProvider) { + return new LinkSpanDrawable.LinksTextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + heightMeasureSpec + ); + } + }; + } + + @Override + public void bindView(View view, UItem item, boolean divider) { + final LinkSpanDrawable.LinksTextView textView = (LinkSpanDrawable.LinksTextView) view; + textView.setGravity(item.intValue); + textView.setTextColor((int) item.longValue); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, item.floatValue); + textView.setTypeface(item.checked ? null : AndroidUtilities.bold()); + textView.setPadding(item.pad, 0, item.pad, 0); + textView.setText(item.text); + } + + public static UItem asBoldText(int color, int gravity, float textSizeDp, CharSequence text) { + return asText(color, gravity, textSizeDp, text, true, 0); + } + + public static UItem asText(int color, int gravity, float textSizeDp, CharSequence text) { + return asText(color, gravity, textSizeDp, text, false, 0); + } + + public static UItem asText(int color, int gravity, float textSizeDp, CharSequence text, boolean bold, int padding) { + UItem item = UItem.ofFactory(TextFactory.class); + item.text = text; + item.intValue = gravity; + item.longValue = color; + item.floatValue = textSizeDp; + item.pad = padding; + item.checked = bold; + return item; + } + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Gifts/SendGiftSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Gifts/SendGiftSheet.java new file mode 100644 index 0000000000..343e63d6a9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Gifts/SendGiftSheet.java @@ -0,0 +1,634 @@ +package org.telegram.ui.Gifts; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.lerp; +import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DefaultItemAnimator; + +import com.android.billingclient.api.BillingClient; +import com.android.billingclient.api.BillingFlowParams; +import com.android.billingclient.api.ProductDetails; +import com.google.zxing.common.detector.MathUtils; + +import org.telegram.messenger.AccountInstance; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationNotificationsLocker; +import org.telegram.messenger.BillingController; +import org.telegram.messenger.BuildVars; +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; +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.tgnet.tl.TL_stars; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.INavigationLayout; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ChatActionCell; +import org.telegram.ui.Cells.EditEmojiTextCell; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.EditTextEmoji; +import org.telegram.ui.Components.EditTextSuggestionsFix; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftSentBottomSheet; +import org.telegram.ui.Components.RecyclerListView; +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.LaunchActivity; +import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stars.StarsController; +import org.telegram.ui.Stars.StarsIntroActivity; +import org.telegram.ui.Stars.StarsReactionsSheet; +import org.telegram.ui.Stories.bots.BotPreviewsEditContainer; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; +import org.telegram.ui.Stories.recorder.PreviewView; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class SendGiftSheet extends BottomSheetWithRecyclerListView { + + private final int currentAccount; + private final long dialogId; + private final TL_stars.StarGift starGift; + private final GiftPremiumBottomSheet.GiftTier premiumTier; + private final String name; + private final Runnable closeParentSheet; + + private final SizeNotifierFrameLayout chatView; + private final ChatActionCell actionCell; + + private final TLRPC.MessageAction action; + private final MessageObject messageObject; + + private final LinearLayout buttonContainer; + private final ButtonWithCounterView button; + + private final FrameLayout limitContainer; + private final View limitProgressView; + private final FrameLayout valueContainerView; + private final TextView soldTextView, soldTextView2; + private final TextView leftTextView, leftTextView2; + + public boolean anonymous; + + private EditEmojiTextCell messageEdit; + + private UniversalAdapter adapter; + + public final AnimationNotificationsLocker animationsLock = new AnimationNotificationsLocker(); + + public SendGiftSheet(Context context, int currentAccount, TL_stars.StarGift gift, long dialogId, Runnable closeParentSheet) { + this(context, currentAccount, gift, null, dialogId, closeParentSheet); + } + + public SendGiftSheet(Context context, int currentAccount, GiftPremiumBottomSheet.GiftTier premiumTier, long dialogId, Runnable closeParentSheet) { + this(context, currentAccount, null, premiumTier, dialogId, closeParentSheet); + } + + private SendGiftSheet(Context context, int currentAccount, TL_stars.StarGift starGift, GiftPremiumBottomSheet.GiftTier premiumTier, long dialogId, Runnable closeParentSheet) { + super(context, null, true, false, false, false, ActionBarType.SLIDING, null); + + setImageReceiverNumLevel(0, 4); + fixNavigationBar(); +// setSlidingActionBar(); + headerPaddingTop = dp(4); + headerPaddingBottom = dp(-10); + + this.currentAccount = currentAccount; + this.dialogId = dialogId; + this.starGift = starGift; + this.premiumTier = premiumTier; + this.closeParentSheet = closeParentSheet; + + topPadding = 0.2f; + + final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + this.name = UserObject.getForcedFirstName((TLRPC.User) user); + + actionCell = new ChatActionCell(context, false, resourcesProvider); + actionCell.setDelegate(new ChatActionCell.ChatActionCellDelegate() {}); + + chatView = new SizeNotifierFrameLayout(context) { + @Override + protected boolean isActionBarVisible() { + return false; + } + @Override + protected boolean isStatusBarVisible() { + return false; + } + @Override + protected boolean useRootView() { + return false; + } + int maxHeight = -1; + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (maxHeight != -1) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (getMeasuredHeight() < maxHeight) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(maxHeight, getMeasuredHeight()), MeasureSpec.AT_MOST); + } + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (maxHeight == -1) { + maxHeight = Math.max(maxHeight, getMeasuredHeight()); + } + } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + actionCell.setTranslationY(((b - t) - actionCell.getMeasuredHeight()) / 2f - dp(8)); + actionCell.setVisiblePart(actionCell.getY(), getBackgroundSizeY()); + } + }; + chatView.setBackgroundImage(PreviewView.getBackgroundDrawable(null, currentAccount, dialogId, Theme.isCurrentThemeDark()), false); + + if (starGift != null) { + TLRPC.TL_messageActionStarGift action = new TLRPC.TL_messageActionStarGift(); + action.gift = starGift; + action.flags |= 2; + action.message = new TLRPC.TL_textWithEntities(); + action.convert_stars = this.starGift.convert_stars; + action.forceIn = true; + this.action = action; + } else if (premiumTier != null && premiumTier.giftCodeOption != null) { + TLRPC.TL_messageActionGiftCode action = new TLRPC.TL_messageActionGiftCode(); + action.unclaimed = true; + action.via_giveaway = false; + action.months = premiumTier.getMonths(); + action.flags |= 4; + action.currency = premiumTier.getCurrency(); + action.amount = premiumTier.getPrice(); + if (premiumTier.googlePlayProductDetails != null) { + action.amount = (long) (action.amount * Math.pow(10, BillingController.getInstance().getCurrencyExp(action.currency) - 6)); + } + action.flags |= 16; + action.message = new TLRPC.TL_textWithEntities(); + this.action = action; + } else if (premiumTier != null && premiumTier.giftOption != null) { + TLRPC.TL_messageActionGiftPremium action = new TLRPC.TL_messageActionGiftPremium(); + action.months = premiumTier.getMonths(); + action.currency = premiumTier.getCurrency(); + action.amount = premiumTier.getPrice(); + if (premiumTier.googlePlayProductDetails != null) { + action.amount = (long) (action.amount * Math.pow(10, BillingController.getInstance().getCurrencyExp(action.currency) - 6)); + } + action.flags |= 2; + action.message = new TLRPC.TL_textWithEntities(); + this.action = action; + } else { + throw new RuntimeException("SendGiftSheet with no star gift and no premium tier"); + } + + TLRPC.TL_messageService message = new TLRPC.TL_messageService(); + message.id = 1; + message.dialog_id = dialogId; + message.from_id = MessagesController.getInstance(currentAccount).getPeer(UserConfig.getInstance(currentAccount).getClientUserId()); + message.peer_id = MessagesController.getInstance(currentAccount).getPeer(UserConfig.getInstance(currentAccount).getClientUserId()); + message.action = action; + + messageObject = new MessageObject(currentAccount, message, false, false); + actionCell.setMessageObject(messageObject, true); + + chatView.addView(actionCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 8, 0, 8)); + + messageEdit = new EditEmojiTextCell(context, (SizeNotifierFrameLayout) containerView, getString(starGift != null ? R.string.Gift2Message : R.string.Gift2MessageOptional), true, MessagesController.getInstance(currentAccount).stargiftsMessageLengthMax, EditTextEmoji.STYLE_GIFT, resourcesProvider) { + @Override + protected void onTextChanged(CharSequence newText) { + TLRPC.TL_textWithEntities txt; + if (action instanceof TLRPC.TL_messageActionStarGift) { + txt = ((TLRPC.TL_messageActionStarGift) action).message = new TLRPC.TL_textWithEntities(); + } else if (action instanceof TLRPC.TL_messageActionGiftCode) { + ((TLRPC.TL_messageActionGiftCode) action).flags |= 16; + txt = ((TLRPC.TL_messageActionGiftCode) action).message = new TLRPC.TL_textWithEntities(); + } else if (action instanceof TLRPC.TL_messageActionGiftPremium) { + ((TLRPC.TL_messageActionGiftPremium) action).flags |= 16; + txt = ((TLRPC.TL_messageActionGiftPremium) action).message = new TLRPC.TL_textWithEntities(); + } else return; + CharSequence[] msg = new CharSequence[] { messageEdit.getText() }; + txt.entities = MediaDataController.getInstance(currentAccount).getEntities(msg, true); + txt.text = msg[0].toString(); + messageObject.setType(); + actionCell.setMessageObject(messageObject, true); + adapter.update(true); + } + + @Override + protected void onFocusChanged(boolean focused) { + + } + }; + messageEdit.editTextEmoji.getEditText().addTextChangedListener(new EditTextSuggestionsFix()); + messageEdit.editTextEmoji.allowEmojisForNonPremium(true); + messageEdit.setShowLimitWhenNear(50); + setEditTextEmoji(messageEdit.editTextEmoji); + messageEdit.setShowLimitOnFocus(true); + messageEdit.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + messageEdit.setDivider(false); + messageEdit.hideKeyboardOnEnter(); + messageEdit.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + + final DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { + @Override + protected float animateByScale(View view) { + return .3f; + } + }; + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayIncrement(40); + recyclerListView.setItemAnimator(itemAnimator); + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(48 + 10 + 10 + (starGift != null && starGift.limited ? 30 + 10 : 0))); + adapter.update(false); + + recyclerListView.setOnItemClickListener((view, position) -> { + final UItem item = adapter.getItem(reverseLayout ? position : position - 1); + if (item == null) return; + if (item.id == 1) { + anonymous = !anonymous; + if (action instanceof TLRPC.TL_messageActionStarGift) { + ((TLRPC.TL_messageActionStarGift) action).name_hidden = anonymous; + } + messageObject.updateMessageText(); + actionCell.setMessageObject(messageObject, true); + adapter.update(true); + } + }); + + buttonContainer = new LinearLayout(context); + buttonContainer.setOrientation(LinearLayout.VERTICAL); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + buttonContainer.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + containerView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.BOTTOM)); + + final View buttonShadow = new View(context); + buttonShadow.setBackgroundColor(Theme.getColor(Theme.key_dialogGrayLine, resourcesProvider)); + buttonContainer.addView(buttonShadow, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 1f / AndroidUtilities.density, Gravity.FILL_HORIZONTAL | Gravity.TOP)); + + final float limitedProgress = Utilities.clamp(starGift == null ? 0 : (float) starGift.availability_remains / starGift.availability_total, 0.97f, 0); + limitContainer = new FrameLayout(context); + limitContainer.setVisibility(starGift != null && starGift.limited ? View.VISIBLE : View.GONE); + limitContainer.setBackground(Theme.createRoundRectDrawable(dp(6), Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider))); + buttonContainer.addView(limitContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 30, 10, 10, 10, 0)); + + leftTextView = new TextView(context); + leftTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + leftTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + leftTextView.setTypeface(AndroidUtilities.bold()); + leftTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + if (starGift != null) { + leftTextView.setText(LocaleController.formatPluralStringComma("Gift2AvailabilityLeft", starGift.availability_remains)); + } + limitContainer.addView(leftTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT, 11, 0, 11, 0)); + + soldTextView = new TextView(context); + soldTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + soldTextView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL); + soldTextView.setTypeface(AndroidUtilities.bold()); + soldTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + if (starGift != null) { + soldTextView.setText(LocaleController.formatPluralStringComma("Gift2AvailabilitySold", starGift.availability_total - starGift.availability_remains)); + } + limitContainer.addView(soldTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT, 11, 0, 11, 0)); + + limitProgressView = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (starGift == null) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } + super.onMeasure(MeasureSpec.makeMeasureSpec((int) (MeasureSpec.getSize(widthMeasureSpec) * limitedProgress), MeasureSpec.EXACTLY), heightMeasureSpec); + } + }; + limitProgressView.setBackground(Theme.createRoundRectDrawable(dp(6), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider))); + limitContainer.addView(limitProgressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); + + valueContainerView = new FrameLayout(context) { + @Override + protected void dispatchDraw(@NonNull Canvas canvas) { + canvas.save(); + canvas.clipRect(0, 0, getWidth() * limitedProgress, getHeight()); + super.dispatchDraw(canvas); + canvas.restore(); + } + }; + valueContainerView.setWillNotDraw(false); + limitContainer.addView(valueContainerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); + + leftTextView2 = new TextView(context); + leftTextView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + leftTextView2.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + leftTextView2.setTypeface(AndroidUtilities.bold()); + leftTextView2.setTextColor(0xFFFFFFFF); + if (starGift != null) { + leftTextView2.setText(LocaleController.formatPluralStringComma("Gift2AvailabilityLeft", starGift.availability_remains)); + } + valueContainerView.addView(leftTextView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT, 11, 0, 11, 0)); + + soldTextView2 = new TextView(context); + soldTextView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + soldTextView2.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL); + soldTextView2.setTypeface(AndroidUtilities.bold()); + soldTextView2.setTextColor(0xFFFFFFFF); + if (starGift != null) { + soldTextView2.setText(LocaleController.formatPluralStringComma("Gift2AvailabilitySold", starGift.availability_total - starGift.availability_remains)); + } + valueContainerView.addView(soldTextView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT, 11, 0, 11, 0)); + + button = new ButtonWithCounterView(context, resourcesProvider); + if (starGift != null) { + button.setText(StarsIntroActivity.replaceStars(LocaleController.formatPluralStringComma("Gift2Send", (int) this.starGift.stars)), false); + } else if (premiumTier != null) { + button.setText(LocaleController.formatString(R.string.Gift2SendPremium, premiumTier.getFormattedPrice()), false); + } + buttonContainer.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 10, 10, 10, 10)); + button.setOnClickListener(v -> { + if (button.isLoading()) return; + button.setLoading(true); + if (messageEdit.editTextEmoji.getEmojiPadding() > 0) { + messageEdit.editTextEmoji.hidePopup(true); + } else if (messageEdit.editTextEmoji.isKeyboardVisible()) { + messageEdit.editTextEmoji.closeKeyboard(); + } + if (starGift != null) { + buyStarGift(); + } else { + buyPremiumTier(); + } + }); + + layoutManager.setReverseLayout(reverseLayout = true); + adapter.update(false); + layoutManager.scrollToPositionWithOffset(adapter.getItemCount(), dp(200)); + } + + private TLRPC.TL_textWithEntities getMessage() { + if (action instanceof TLRPC.TL_messageActionStarGift) { + return ((TLRPC.TL_messageActionStarGift) action).message; + } else if (action instanceof TLRPC.TL_messageActionGiftCode) { + return ((TLRPC.TL_messageActionGiftCode) action).message; + } else if (action instanceof TLRPC.TL_messageActionGiftPremium) { + return ((TLRPC.TL_messageActionGiftPremium) action).message; + } else { + return null; + } + } + + private void buyStarGift() { + StarsController.getInstance(currentAccount).buyStarGift( + AndroidUtilities.getActivity(getContext()), + this.starGift, + anonymous, + dialogId, + getMessage(), + (status, err) -> { + if (status) { + if (closeParentSheet != null) { + closeParentSheet.run(); + } + AndroidUtilities.hideKeyboard(messageEdit); + dismiss(); + } else if ("STARGIFT_USAGE_LIMITED".equalsIgnoreCase(err)) { + AndroidUtilities.hideKeyboard(messageEdit); + dismiss(); + StarsController.getInstance(currentAccount).makeStarGiftSoldOut(starGift); + return; + } + button.setLoading(false); + } + ); + } + + private void buyPremiumTier() { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + if (user == null) { + button.setLoading(false); + return; + } + if (premiumTier.giftCodeOption != null) { + final BaseFragment fragment = new BaseFragment() { + @Override + public Activity getParentActivity() { + Activity activity = getOwnerActivity(); + if (activity == null) activity = LaunchActivity.instance; + if (activity == null) + activity = AndroidUtilities.findActivity(SendGiftSheet.this.getContext()); + return activity; + } + + @Override + public Theme.ResourcesProvider getResourceProvider() { + return SendGiftSheet.this.resourcesProvider; + } + }; + BoostRepository.payGiftCode(new ArrayList<>(Arrays.asList(user)), premiumTier.giftCodeOption, null, getMessage(), fragment, result -> { + if (closeParentSheet != null) { + closeParentSheet.run(); + } + dismiss(); + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.giftsToUserSent); + AndroidUtilities.runOnUIThread(() -> PremiumPreviewGiftSentBottomSheet.show(new ArrayList<>(Arrays.asList(user))), 250); + }, error -> { + BoostDialogs.showToastError(getContext(), error); + }); + return; + } + if (BuildVars.useInvoiceBilling()) { + final LaunchActivity activity = LaunchActivity.instance; + if (activity != null) { + Uri uri = Uri.parse(premiumTier.giftOption.bot_url); + if (uri.getHost().equals("t.me")) { + if (!uri.getPath().startsWith("/$") && !uri.getPath().startsWith("/invoice/")) { + activity.setNavigateToPremiumBot(true); + } else { + activity.setNavigateToPremiumGiftCallback(() -> onGiftSuccess(false)); + } + } + Browser.openUrl(activity, premiumTier.giftOption.bot_url); + dismiss(); + } + } else { + if (BillingController.getInstance().isReady() && premiumTier.googlePlayProductDetails != null) { + TLRPC.TL_inputStorePaymentGiftPremium giftPremium = new TLRPC.TL_inputStorePaymentGiftPremium(); + giftPremium.user_id = MessagesController.getInstance(currentAccount).getInputUser(user); + ProductDetails.OneTimePurchaseOfferDetails offerDetails = premiumTier.googlePlayProductDetails.getOneTimePurchaseOfferDetails(); + giftPremium.currency = offerDetails.getPriceCurrencyCode(); + giftPremium.amount = (long) ((offerDetails.getPriceAmountMicros() / Math.pow(10, 6)) * Math.pow(10, BillingController.getInstance().getCurrencyExp(giftPremium.currency))); + + BillingController.getInstance().addResultListener(premiumTier.giftOption.store_product, billingResult -> { + if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { + AndroidUtilities.runOnUIThread(() -> onGiftSuccess(true)); + } + }); + + TLRPC.TL_payments_canPurchasePremium req = new TLRPC.TL_payments_canPurchasePremium(); + req.purpose = giftPremium; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{ + if (response instanceof TLRPC.TL_boolTrue) { + BillingController.getInstance().launchBillingFlow(getBaseFragment().getParentActivity(), AccountInstance.getInstance(currentAccount), giftPremium, Collections.singletonList(BillingFlowParams.ProductDetailsParams.newBuilder() + .setProductDetails(premiumTier.googlePlayProductDetails) + .build())); + } else if (error != null) { + AlertsCreator.processError(currentAccount, error, getBaseFragment(), req); + } + })); + } + } + } + + private void onGiftSuccess(boolean fromGooglePlay) { + TLRPC.UserFull full = MessagesController.getInstance(currentAccount).getUserFull(dialogId); + final TLObject user = MessagesController.getInstance(currentAccount).getUserOrChat(dialogId); + if (full != null) { + if (user instanceof TLRPC.User) { + ((TLRPC.User) user).premium = true; + MessagesController.getInstance(currentAccount).putUser((TLRPC.User) user, true); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.userInfoDidLoad, ((TLRPC.User) user).id, full); + } + } + + if (getBaseFragment() != null) { + List fragments = new ArrayList<>(((LaunchActivity) getBaseFragment().getParentActivity()).getActionBarLayout().getFragmentStack()); + + INavigationLayout layout = getBaseFragment().getParentLayout(); + ChatActivity lastChatActivity = null; + for (BaseFragment fragment : fragments) { + if (fragment instanceof ChatActivity) { + lastChatActivity = (ChatActivity) fragment; + if (lastChatActivity.getDialogId() != dialogId) { + fragment.removeSelfFromStack(); + } + } else if (fragment instanceof ProfileActivity) { + if (fromGooglePlay && layout.getLastFragment() == fragment) { + fragment.finishFragment(); + } else { + fragment.removeSelfFromStack(); + } + } + } + if (lastChatActivity == null || lastChatActivity.getDialogId() != dialogId) { + Bundle args = new Bundle(); + args.putLong("user_id", dialogId); + layout.presentFragment(new ChatActivity(args), true); + } + } + + dismiss(); + } + + @Override + protected CharSequence getTitle() { + return getString(R.string.Gift2Title); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + adapter = new UniversalAdapter(recyclerListView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider); + adapter.setApplyBackground(false); + return adapter; + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + items.add(UItem.asCustom(-1, chatView)); + items.add(UItem.asCustom(-2, messageEdit)); + if (starGift != null) { + items.add(UItem.asShadow(-3, null)); + items.add(UItem.asCheck(1, getString(R.string.Gift2Hide)).setChecked(anonymous)); + items.add(UItem.asShadow(-4, formatString(R.string.Gift2HideInfo, name))); + } else { + items.add(UItem.asShadow(-3, formatString(R.string.Gift2MessagePremiumInfo, name))); + } + if (reverseLayout) Collections.reverse(items); + } + + @Override + public void show() { + if (messageEdit != null) { + messageEdit.editTextEmoji.onResume(); + } + super.show(); + } + + @Override + public void dismiss() { + if (messageEdit.editTextEmoji.getEmojiPadding() > 0) { + messageEdit.editTextEmoji.hidePopup(true); + return; + } else if (messageEdit.editTextEmoji.isKeyboardVisible()) { + messageEdit.editTextEmoji.closeKeyboard(); + return; + } + if (messageEdit != null) { + messageEdit.editTextEmoji.onPause(); + } + super.dismiss(); + } + + @Override + public void onBackPressed() { + if (messageEdit.editTextEmoji.getEmojiPadding() > 0) { + messageEdit.editTextEmoji.hidePopup(true); + return; + } else if (messageEdit.editTextEmoji.isKeyboardVisible()) { + messageEdit.editTextEmoji.closeKeyboard(); + return; + } + super.onBackPressed(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GradientClip.java b/TMessagesProj/src/main/java/org/telegram/ui/GradientClip.java index 29e9db2cf0..fdf8149317 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GradientClip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GradientClip.java @@ -72,4 +72,15 @@ public Paint getPaint(int dir, float alpha) { return paint[dir]; } + public void clipOut(Canvas canvas, RectF rect, float alpha) { + final int dir = 0; + if (paint[dir] == null) { + paint[dir] = new Paint(Paint.ANTI_ALIAS_FLAG); + if (!DEBUG) paint[dir].setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + } + paint[dir].setShader(gradient); + paint[dir].setAlpha((int) (0xFF * alpha)); + canvas.drawRect(rect, paint[dir]); + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java index 0164040fbd..ac103766e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java @@ -38,6 +38,7 @@ import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.FillLastLinearLayoutManager; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; import org.telegram.ui.Components.NestedSizeNotifierLayout; import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.Premium.StarParticlesView; @@ -196,10 +197,10 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { }); backgroundView = new BackgroundView(context) { - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return true; - } +// @Override +// public boolean onInterceptTouchEvent(MotionEvent ev) { +// return true; +// } }; contentView.addView(particlesView = createParticlesView(), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -234,6 +235,7 @@ public ContentView(Context context) { int lastSize; boolean topInterceptedTouch; + boolean subtitleInterceptedTouch; boolean bottomInterceptedTouch; @Override @@ -259,8 +261,25 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override public boolean dispatchTouchEvent(MotionEvent ev) { BackgroundView backgroundView = GradientHeaderActivity.this.backgroundView; - float topX = backgroundView.getX() + backgroundView.aboveTitleLayout.getX(); - float topY = backgroundView.getY() + backgroundView.aboveTitleLayout.getY(); + + float topX = backgroundView.getX() + backgroundView.subtitleView.getX(); + float topY = backgroundView.getY() + backgroundView.subtitleView.getY(); + AndroidUtilities.rectTmp.set(topX, topY, + topX + backgroundView.subtitleView.getMeasuredWidth(), + topY + backgroundView.subtitleView.getMeasuredHeight()); + if ((AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || subtitleInterceptedTouch) && !listView.scrollingByUser && backgroundView.subtitleView.hasLinks() && progressToFull < 1) { + ev.offsetLocation(-topX, -topY); + if (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) { + subtitleInterceptedTouch = true; + } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + subtitleInterceptedTouch = false; + } + backgroundView.subtitleView.dispatchTouchEvent(ev); + return true; + } + + topX = backgroundView.getX() + backgroundView.aboveTitleLayout.getX(); + topY = backgroundView.getY() + backgroundView.aboveTitleLayout.getY(); boolean isClickableTop = backgroundView.aboveTitleLayout.isClickable(); AndroidUtilities.rectTmp.set(topX, topY, topX + backgroundView.aboveTitleLayout.getMeasuredWidth(), @@ -499,9 +518,11 @@ private void updateColors() { if (whiteBackground) { backgroundView.titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); backgroundView.subtitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + backgroundView.subtitleView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn)); } else { backgroundView.titleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); backgroundView.subtitleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); + backgroundView.subtitleView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn)); } } updateBackgroundImage(); @@ -538,7 +559,7 @@ public void onPause() { protected static class BackgroundView extends LinearLayout { private final TextView titleView; - public final TextView subtitleView; + public final LinkSpanDrawable.LinksTextView subtitleView; private final FrameLayout aboveTitleLayout; private final FrameLayout belowSubTitleLayout; @@ -556,7 +577,7 @@ public BackgroundView(Context context) { titleView.setGravity(Gravity.CENTER_HORIZONTAL); addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_HORIZONTAL, 16, 20, 16, 0)); - subtitleView = new TextView(context); + subtitleView = new LinkSpanDrawable.LinksTextView(context); subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f); subtitleView.setGravity(Gravity.CENTER_HORIZONTAL); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index f042147ad7..ad163a32b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -80,6 +80,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; @@ -116,6 +117,7 @@ import org.telegram.ui.Cells.GroupCallTextCell; import org.telegram.ui.Cells.GroupCallUserCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.Components.AvatarDrawable; @@ -134,6 +136,7 @@ import org.telegram.ui.Components.JoinCallAlert; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.NumberPicker; +import org.telegram.ui.Components.PermissionRequest; import org.telegram.ui.Components.ProfileGalleryView; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; @@ -151,7 +154,9 @@ import org.telegram.ui.Components.voip.GroupCallStatusIcon; import org.telegram.ui.Components.voip.PrivateVideoPreviewDialog; import org.telegram.ui.Components.voip.RTMPStreamPipOverlay; +import org.telegram.ui.Components.voip.VoIPTextureView; import org.telegram.ui.Components.voip.VoIPToggleButton; +import org.telegram.ui.Stories.recorder.DominantColors; import org.webrtc.voiceengine.WebRtcAudioTrack; import java.io.File; @@ -280,6 +285,8 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private final Matrix radialMatrix; private final Paint radialPaint; + private LightningView textureLightningView; + private float switchToButtonProgress; private float switchToButtonInt2; private float scheduleButtonsScale; @@ -297,6 +304,11 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private RecordCallDrawable recordCallDrawable; private AudioPlayerAlert.ClippingTextViewSwitcher titleTextView; + private TextView liveLabelTextView; + private Paint liveLabelPaint; + private ValueAnimator liveLabelBgColorAnimator; + private float textureLightningViewAnimatingAlpha; + private LinearLayout titleLayout; private ActionBarMenuItem otherItem; private ActionBarMenuItem pipItem; private ActionBarMenuItem screenShareItem; @@ -312,6 +324,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private ActionBarMenuSubItem leaveItem; private final LinearLayout menuItemsContainer; private View soundItemDivider; + private WatchersView watchersView; private Runnable updateCallRecordRunnable; @@ -435,6 +448,54 @@ public void run() { pressed = true; }; + public static volatile DispatchQueue updateTextureLightningQueue = new DispatchQueue("updateTextureLightningQueue"); + + private boolean needTextureLightning = false; + private final Runnable updateTextureLightningRunnable = new Runnable() { + @Override + public void run() { + try { + if (renderersContainer == null || renderersContainer.inFullscreenMode) return; + final GroupCallGridCell cell = findGroupCallGridCell(); + if (cell == null) return; + final GroupCallMiniTextureView rendered = cell.getRenderer(); + if (rendered == null) return; + final VoIPTextureView textureView = rendered.textureView; + if (textureView == null) return; + updateTextureLightningQueue.postRunnable(() -> { + try { + Bitmap bitmap = textureView.blurRenderer.getBitmap(100, 100); + if (bitmap == null) return; + int[] bitmapColors = DominantColors.getColorsSync(false, bitmap, true); + AndroidUtilities.runOnUIThread(() -> textureLightningView.setNewColors(bitmapColors)); + } catch (Exception e2) { + FileLog.e(e2); + } + }); + } catch (Exception e) { + FileLog.e(e); + } + } + }; + + private GroupCallGridCell findGroupCallGridCell() { + for (int i = 0; i < listView.getChildCount(); i++) { + View view = listView.getChildAt(i); + if (view instanceof GroupCallGridCell && listView.getChildAdapterPosition(view) >= 0) { + return (GroupCallGridCell) view; + } + } + return null; + } + + private void runUpdateTextureLightningRunnable() { + AndroidUtilities.cancelRunOnUIThread(updateTextureLightningRunnable); + if (!needTextureLightning || textureLightningView == null || VoIPService.getSharedInstance() == null || !isRtmpStream() || listView == null || !LiteMode.isEnabled(LiteMode.FLAG_CALLS_ANIMATIONS)) { + return; + } + AndroidUtilities.runOnUIThread(updateTextureLightningRunnable, 30); + } + LongSparseIntArray visiblePeerIds = new LongSparseIntArray(); public static final Property COLOR_PROGRESS = new AnimationProperties.FloatProperty("colorProgress") { @@ -1645,10 +1706,10 @@ private void updateItems() { otherItem.setVisibility(View.VISIBLE); } - FrameLayout.LayoutParams layoutParams = ((FrameLayout.LayoutParams) titleTextView.getLayoutParams()); + FrameLayout.LayoutParams layoutParams = ((FrameLayout.LayoutParams) titleLayout.getLayoutParams()); if (layoutParams.rightMargin != AndroidUtilities.dp(margin)) { layoutParams.rightMargin = AndroidUtilities.dp(margin); - titleTextView.requestLayout(); + titleLayout.requestLayout(); } ((FrameLayout.LayoutParams) menuItemsContainer.getLayoutParams()).rightMargin = 0; @@ -2089,7 +2150,7 @@ public void afterTextChanged(Editable s) { alertDialog.setTextColor(Theme.getColor(Theme.key_voipgroup_nameText)); editText.requestFocus(); } else if (id == user_item) { - JoinCallAlert.open(getContext(), -currentChat.id, accountInstance, null, JoinCallAlert.TYPE_DISPLAY, selfPeer, (peer1, hasFewPeers, schedule) -> { + JoinCallAlert.open(getContext(), -currentChat.id, accountInstance, null, JoinCallAlert.TYPE_DISPLAY, selfPeer, (peer1, hasFewPeers, schedule, isRtmpStream) -> { if (call == null) { return; } @@ -2313,7 +2374,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { measuredWidth = muteButton.getLayoutParams().width; } float muteButtonScale = AndroidUtilities.dp(52) / (float) (measuredWidth - AndroidUtilities.dp(8)); - float multiplier = isLandscapeMode ? muteButtonScale : renderersContainer.inFullscreenMode ? muteButtonScale : 1f; + float multiplier = isLandscapeMode || isRtmpStream() ? muteButtonScale : renderersContainer.inFullscreenMode ? muteButtonScale : 1f; boolean isExpanded = renderersContainer.inFullscreenMode && (AndroidUtilities.isTablet() || isLandscapeMode == isRtmpLandscapeMode()); View expandView = isExpanded ? minimizeButton : expandButton; @@ -2390,7 +2451,12 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (Build.VERSION.SDK_INT >= 21) { setPadding(backgroundPaddingLeft, getStatusBarHeight(), backgroundPaddingLeft, 0); } - int availableHeight = totalHeight - getPaddingTop() - AndroidUtilities.dp(14 + 231); + int availableHeight = totalHeight - getPaddingTop(); + if (isRtmpStream()) { + availableHeight -= AndroidUtilities.dp(72); + } else { + availableHeight -= AndroidUtilities.dp(14 + 231); + } int listViewPaddingBottom; @@ -2415,7 +2481,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { layoutParams.topMargin = ActionBar.getCurrentActionBarHeight(); } - int buttonsGradientSize = AndroidUtilities.dp(150); + int buttonsGradientSize = AndroidUtilities.dp(isRtmpStream() ? 100 : 150); //listView layoutParams layoutParams = (LayoutParams) listView.getLayoutParams(); if (isTabletMode) { @@ -2541,6 +2607,28 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (listView.getPaddingTop() != padding || listView.getPaddingBottom() != listViewPaddingBottom) { listView.setPadding(0, padding, 0, listViewPaddingBottom); } + + if (watchersView != null) { + layoutParams = (LayoutParams) watchersView.getLayoutParams(); + GroupCallGridCell cell = findGroupCallGridCell(); + if (cell != null) { + int leaveButtonTop = buttonsContainer.getTop() + buttonsContainer.getMeasuredHeight() / 2 - leaveButton.getMeasuredHeight() / 2; + int top = padding + ActionBar.getCurrentActionBarHeight() + cell.getMeasuredHeight(); + int diff = (leaveButtonTop - top) / 2; + layoutParams.topMargin = top + diff - AndroidUtilities.dp(32); + layoutParams.height = AndroidUtilities.dp(70); + } + } + + if (textureLightningView != null) { + layoutParams = (LayoutParams) textureLightningView.getLayoutParams(); + GroupCallGridCell cell = findGroupCallGridCell(); + if (cell != null) { + layoutParams.height = cell.getMeasuredHeight() - AndroidUtilities.dp(14); + layoutParams.width = cell.getMeasuredWidth() - AndroidUtilities.dp(7); + layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(16); + } + } if (scheduleStartAtTextView != null) { int y = padding + (availableHeight - padding + AndroidUtilities.dp(60)) / 2; FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) scheduleStartInTextView.getLayoutParams(); @@ -2690,6 +2778,20 @@ protected void onDraw(Canvas canvas) { Theme.dialogs_onlineCirclePaint.setColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_voipgroup_actionBar), (int) (255 * renderersContainer.progressToFullscreenMode))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), Theme.dialogs_onlineCirclePaint); } + if (isRtmpStream() && LiteMode.isEnabled(LiteMode.FLAG_CALLS_ANIMATIONS)) { + if (renderersContainer.progressToFullscreenMode < 0.15) { + if (!needTextureLightning) { + needTextureLightning = true; + runUpdateTextureLightningRunnable(); + } + } else { + if (needTextureLightning) { + needTextureLightning = false; + AndroidUtilities.cancelRunOnUIThread(updateTextureLightningRunnable); + } + } + } + } HashMap listCells = new HashMap<>(); @@ -2816,6 +2918,11 @@ protected void dispatchDraw(Canvas canvas) { } else { listView.setAlpha(1f); } + + if (watchersView != null) { + watchersView.setAlpha(1f - renderersContainer.progressToFullscreenMode); + watchersView.setTranslationY(renderersContainer.progressToFullscreenMode * AndroidUtilities.dp(64)); + } super.dispatchDraw(canvas); if (drawingForBlur) { return; @@ -3009,7 +3116,7 @@ protected void dispatchDraw(Canvas canvas) { @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (!isTabletMode && renderersContainer.progressToFullscreenMode == 1f && (child == actionBar || child == actionBarShadow || child == actionBarBackground || child == titleTextView || child == menuItemsContainer)) { + if (!isTabletMode && renderersContainer.progressToFullscreenMode == 1f && (child == actionBar || child == actionBarShadow || child == actionBarBackground || child == titleTextView || child == menuItemsContainer || child == textureLightningView)) { return true; } if (drawingForBlur && child == renderersContainer) { @@ -3145,6 +3252,10 @@ protected void onDraw(Canvas canvas) { scheduleStartAtTextView.setTextSize(18); containerView.addView(scheduleStartAtTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 21, 0, 21, 231 - 30)); //+ 30 } + if (isRtmpStream()) { + textureLightningView = new LightningView(context); + containerView.addView(textureLightningView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80, Gravity.TOP | Gravity.LEFT, 0, 44, 0, 0)); + } listView = new RecyclerListView(context) { @@ -3265,6 +3376,9 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { call.loadMembers(false); } updateLayout(true); + if (textureLightningView != null) { + textureLightningView.invalidate(); + } containerView.invalidate(); } @@ -3425,6 +3539,11 @@ public void needOpenSearch(MotionEvent ev, EditTextBoldCursor editText) { return false; }); + if (isRtmpStream()) { + watchersView = new WatchersView(getContext()); + containerView.addView(watchersView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 0, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0)); + } + tabletVideoGridView = new RecyclerListView(context); containerView.addView(tabletVideoGridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 14, 14, TABLET_LIST_SIZE + 4, 14)); tabletVideoGridView.setAdapter(tabletGridAdapter = new GroupCallTabletGridAdapter(groupCall, currentAccount, this)); @@ -3567,10 +3686,10 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto muteLabel[a].setScaleX(0.687f); muteLabel[a].setScaleY(0.687f); } - } else if (renderersContainer.inFullscreenMode && !isTabletMode) { - + } else if (renderersContainer.inFullscreenMode && !isTabletMode || isRtmpStream()) { int part = getMeasuredWidth() / buttonsCount; - + boolean isRtmpNotFullMode = !renderersContainer.inFullscreenMode && isRtmpStream(); + int yOffset = (isRtmpNotFullMode) ? AndroidUtilities.dp(27) : 0; int x, y; if (soundButton.getVisibility() == View.VISIBLE) { x = part / 2 - cameraButton.getMeasuredWidth() / 2; @@ -3579,7 +3698,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto int partOffset = buttonsCount == 4 ? part : 0; x = part / 2 + partOffset - leaveButton.getMeasuredWidth() / 2; - y = getMeasuredHeight() - soundButton.getMeasuredHeight(); + y = getMeasuredHeight() - soundButton.getMeasuredHeight() - yOffset; soundButton.layout(x, y, x + soundButton.getMeasuredWidth(), y + soundButton.getMeasuredHeight()); } else { int partOffset = buttonsCount == 4 ? part : 0; @@ -3593,13 +3712,13 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto int partOffset = buttonsCount == 4 ? part * 3 : part * 2; x = part / 2 + partOffset - leaveButton.getMeasuredWidth() / 2; - y = getMeasuredHeight() - leaveButton.getMeasuredHeight(); + y = getMeasuredHeight() - leaveButton.getMeasuredHeight() - yOffset; leaveButton.layout(x, y, x + leaveButton.getMeasuredWidth(), y + leaveButton.getMeasuredHeight()); partOffset = buttonsCount == 4 ? part * 2 : part; x = part / 2 + partOffset - muteButton.getMeasuredWidth() / 2; - y = getMeasuredHeight() - leaveButton.getMeasuredHeight() - (muteButton.getMeasuredWidth() - AndroidUtilities.dp(52)) / 2; + y = getMeasuredHeight() - leaveButton.getMeasuredHeight() - (muteButton.getMeasuredWidth() - AndroidUtilities.dp(52)) / 2 - yOffset; muteButton.layout(x, y, x + muteButton.getMeasuredWidth(), y + muteButton.getMeasuredHeight()); minimizeButton.layout(x, y, x + minimizeButton.getMeasuredWidth(), y + minimizeButton.getMeasuredHeight()); expandButton.layout(x, y, x + expandButton.getMeasuredWidth(), y + expandButton.getMeasuredHeight()); @@ -3611,6 +3730,13 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto partOffset = buttonsCount == 4 ? part * 2 : part; x = partOffset + (part - muteLabel[a].getMeasuredWidth()) / 2; y = h - AndroidUtilities.dp(27); + if (isRtmpNotFullMode) { + if (renderersContainer.inFullscreenMode) { + y -= AndroidUtilities.dp(2); + } else { + y -= AndroidUtilities.dp(25); + } + } muteLabel[a].layout(x, y, x + muteLabel[a].getMeasuredWidth(), y + muteLabel[a].getMeasuredHeight()); muteLabel[a].animate().scaleX(0.687f).scaleY(0.687f).setDuration(TRANSITION_DURATION).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } @@ -3847,7 +3973,7 @@ protected void dispatchDraw(Canvas canvas) { bigWaveDrawable.update(amplitude, 1f); tinyWaveDrawable.update(amplitude, 1f); - if (prevState != null && currentState != null && (currentState.currentState == MUTE_BUTTON_STATE_CONNECTING || prevState.currentState == MUTE_BUTTON_STATE_CONNECTING)) { + if (prevState != null && currentState != null && !isRtmpStream() && (currentState.currentState == MUTE_BUTTON_STATE_CONNECTING || prevState.currentState == MUTE_BUTTON_STATE_CONNECTING)) { float progress; if (currentState.currentState == MUTE_BUTTON_STATE_CONNECTING) { progress = switchProgress; @@ -3920,13 +4046,17 @@ protected void dispatchDraw(Canvas canvas) { float alpha; float buttonRadius = AndroidUtilities.dp(57); if (i == 0 && prevState != null) { - paint.setShader(prevState.shader); + if (!isRtmpStream()) { + paint.setShader(prevState.shader); + } alpha = 1f - switchProgress; if (prevState.currentState == MUTE_BUTTON_STATE_CONNECTING) { buttonRadius -= alpha * AndroidUtilities.dp(2); } } else if (i == 1 && currentState != null) { - paint.setShader(currentState.shader); + if (!isRtmpStream()) { + paint.setShader(currentState.shader); + } alpha = switchProgress; if (currentState.currentState == MUTE_BUTTON_STATE_CONNECTING) { buttonRadius -= alpha * AndroidUtilities.dp(2); @@ -3934,10 +4064,17 @@ protected void dispatchDraw(Canvas canvas) { } else { continue; } - if (paint.getShader() == null) { + if (paint.getShader() == null && !isRtmpStream()) { paint.setColor(AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_listViewBackgroundUnscrolled), Theme.getColor(Theme.key_voipgroup_disabledButton), colorProgress, 1.0f)); } + if (isRtmpStream()) { + int bgColor = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_rtmpButton), Theme.getColor(Theme.key_voipgroup_disabledButton), colorProgress, 1.0f); + paint.setColor(bgColor); + paint.setShader(null); + soundButton.setBackgroundColor(AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_listViewBackgroundUnscrolled), Theme.getColor(Theme.key_voipgroup_disabledButton), colorProgress, 1.0f), bgColor); + } + int cx = (int) (muteButton.getX() + muteButton.getMeasuredWidth() / 2); int cy = (int) (muteButton.getY() + muteButton.getMeasuredHeight() / 2); radialMatrix.setTranslate(cx, cy); @@ -3968,7 +4105,7 @@ protected void dispatchDraw(Canvas canvas) { // cy += translation; float scale = BlobDrawable.SCALE_BIG_MIN + BlobDrawable.SCALE_BIG * amplitude * 0.5f; canvas.scale(scale * showLightingProgress, scale * showLightingProgress, cx, cy); - if (i == 1 && LiteMode.isEnabled(LiteMode.FLAG_CALLS_ANIMATIONS)) { + if (i == 1 && !isRtmpStream() && LiteMode.isEnabled(LiteMode.FLAG_CALLS_ANIMATIONS)) { float scaleLight = 0.7f + BlobDrawable.LIGHT_GRADIENT_SIZE * scheduleButtonsScale; canvas.save(); canvas.scale(scaleLight, scaleLight, cx, cy); @@ -3979,7 +4116,7 @@ protected void dispatchDraw(Canvas canvas) { canvas.restore(); } canvas.restore(); - if (switchToButtonProgress > 0) { + if (!isRtmpStream() && switchToButtonProgress > 0) { canvas.save(); scale = BlobDrawable.SCALE_BIG_MIN + BlobDrawable.SCALE_BIG * amplitude * showWavesProgressInterpolated * scheduleButtonsScale; canvas.scale(scale, scale, cx, cy); @@ -4021,6 +4158,9 @@ protected void dispatchDraw(Canvas canvas) { canvas.drawRoundRect(rect, rad, rad, paint); if (i == 1 && currentState.currentState == MUTE_BUTTON_STATE_CONNECTING) { + if (isRtmpStream()) { + radialProgressView.setSize((int) (rad * 2 - AndroidUtilities.dp(4))); + } radialProgressView.draw(canvas, cx, cy); } @@ -4326,6 +4466,14 @@ public void onClick(View v) { updateMuteButton(MUTE_BUTTON_STATE_RAISED_HAND, true); } } else if (muteButtonState == MUTE_BUTTON_STATE_UNMUTE) { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity() != null && getParentActivity().checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + PermissionRequest.ensurePermission(R.raw.permission_request_microphone, R.string.VoipNeedMicPermissionWithHint, Manifest.permission.RECORD_AUDIO, success -> { + if (success) { + // reload mic + } + }); + return; + } updateMuteButton(MUTE_BUTTON_STATE_MUTE, true); VoIPService.getSharedInstance().setMicMute(false, false, true); muteButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); @@ -4356,9 +4504,14 @@ public void onClick(View v) { buttonsContainer.addView(minimizeButton, LayoutHelper.createFrame(122, 122, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); if (call != null && isRtmpStream() && !call.isScheduled()) { + int measuredWidth = expandButton.getMeasuredWidth(); + if (measuredWidth == 0) { + measuredWidth = expandButton.getLayoutParams().width; + } + float expandButtonScale = AndroidUtilities.dp(52) / (float) (measuredWidth - AndroidUtilities.dp(8)); expandButton.setAlpha(1f); - expandButton.setScaleX(1f); - expandButton.setScaleY(1f); + expandButton.setScaleX(expandButtonScale); + expandButton.setScaleY(expandButtonScale); muteButton.setAlpha(0f); } @@ -4439,7 +4592,7 @@ public void onClick(View v) { pipItem = new ActionBarMenuItem(context, null, 0, Theme.getColor(Theme.key_voipgroup_actionBarItems)); pipItem.setLongClickEnabled(false); - pipItem.setIcon((call != null && isRtmpStream()) ? R.drawable.ic_goinline : R.drawable.msg_voice_pip); + pipItem.setIcon(R.drawable.msg_voice_pip); pipItem.setContentDescription(LocaleController.getString(R.string.AccDescrPipMode)); pipItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_voipgroup_actionBarItemsSelector), 6)); pipItem.setOnClickListener(v -> { @@ -4504,8 +4657,37 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { }; actionBarBackground.setAlpha(0.0f); + liveLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + liveLabelPaint.setColor(0xff3d4657); + liveLabelTextView = new TextView(getContext()) { + private RectF rect = new RectF(); + + @Override + protected void onDraw(Canvas canvas) { + rect.set(0, 0, getWidth(), getHeight()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(12), AndroidUtilities.dp(12), liveLabelPaint); + super.onDraw(canvas); + } + }; + liveLabelTextView.setTextColor(getThemedColor(Theme.key_voipgroup_actionBarItems)); + liveLabelTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 11); + liveLabelTextView.setText(LocaleController.getString(R.string.VoipChannelLabelLive)); + liveLabelTextView.setMaxLines(1); + liveLabelTextView.setGravity(Gravity.CENTER); + liveLabelTextView.setTypeface(AndroidUtilities.bold()); + liveLabelTextView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(0), AndroidUtilities.dp(8), AndroidUtilities.dp(0)); + liveLabelTextView.setTag(-1); + if (!isRtmpStream()) { + liveLabelTextView.setVisibility(View.GONE); + } + + titleLayout = new LinearLayout(getContext()); + titleLayout.setOrientation(LinearLayout.HORIZONTAL); + titleLayout.addView(titleTextView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); + titleLayout.addView(liveLabelTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 18, 6, 4, 0,0)); + containerView.addView(actionBarBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); - containerView.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 23, 0, 48, 0)); + containerView.addView(titleLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 23, 0, 48, 0)); containerView.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); menuItemsContainer = new LinearLayout(context); @@ -4720,6 +4902,9 @@ protected void onFullScreenModeChanged(boolean startAnimation) { if (!renderersContainer.inFullscreenMode) { listView.setVisibility(View.VISIBLE); actionBar.setVisibility(View.VISIBLE); + if (watchersView != null) { + watchersView.setVisibility(View.VISIBLE); + } } updateState(true, false); buttonsContainer.requestLayout(); @@ -4738,6 +4923,9 @@ protected void onFullScreenModeChanged(boolean startAnimation) { } else { actionBar.setVisibility(View.GONE); listView.setVisibility(View.GONE); + if (watchersView != null) { + watchersView.setVisibility(View.GONE); + } } if (fullscreenUsersListView.getVisibility() == View.VISIBLE) { @@ -5688,7 +5876,11 @@ private void updateSubtitle() { drawStatus = false; } actionBar.getSubtitleTextView().setText(LocaleController.formatPluralString(isRtmpStream() ? "ViewersWatching" : "Participants", call.call.participants_count + (listAdapter.addSelfToCounter() ? 1 : 0))); - + if (isRtmpStream()) { + if (watchersView != null) { + watchersView.setWatchersCount(call.call.participants_count); + } + } if (drawStatus != drawSpeakingSubtitle) { drawSpeakingSubtitle = drawStatus; actionBar.invalidate(); @@ -5821,7 +6013,11 @@ private void updateTitle(boolean animated) { actionBar.setTitle(currentChat.title); } if (ChatObject.isChannelOrGiga(currentChat)) { - titleTextView.setText(LocaleController.getString(R.string.VoipChannelVoiceChat), animated); + if (isRtmpStream()) { + titleTextView.setText(currentChat.title, animated); + } else { + titleTextView.setText(LocaleController.getString(R.string.VoipChannelVoiceChat), animated); + } } else { titleTextView.setText(LocaleController.getString(R.string.VoipGroupVoiceChat), animated); } @@ -5963,7 +6159,7 @@ private void getLink(boolean copy) { } private void openShareAlert(boolean withMessage, String urlMuted, String urlUnmuted, boolean copy) { - if (isRtmpStream()) { + if (isRtmpStream() && urlMuted != null) { urlUnmuted = null; } if (copy) { @@ -6190,6 +6386,9 @@ private void setScrollOffsetY(float scrollOffsetY) { int willMoveUpTo = offset - backgroundPaddingTop - AndroidUtilities.dp(14) + ActionBar.getCurrentActionBarHeight(); float moveProgress = Math.min(1.0f, (ActionBar.getCurrentActionBarHeight() * 2 - t - backgroundPaddingTop) / willMoveUpTo); diff = (int) (AndroidUtilities.dp(AndroidUtilities.isTablet() ? 17 : 13) * moveProgress); + if (textureLightningView != null) { + textureLightningView.setShadowOffset((int) (AndroidUtilities.dp(8) * moveProgress)); + } float newProgress = Math.min(1.0f, moveProgress); if (Math.abs(newProgress - colorProgress) > 0.0001f) { setColorProgress(Math.min(1.0f, moveProgress)); @@ -6197,18 +6396,27 @@ private void setScrollOffsetY(float scrollOffsetY) { titleTextView.setScaleX(Math.max(0.9f, 1.0f - 0.1f * moveProgress * 1.2f)); titleTextView.setScaleY(Math.max(0.9f, 1.0f - 0.1f * moveProgress * 1.2f)); titleTextView.setAlpha(Math.max(0.0f, 1.0f - moveProgress * 1.2f) * (1f - renderersContainer.progressToFullscreenMode)); + liveLabelTextView.setScaleX(Math.max(0.9f, 1.0f - 0.1f * moveProgress * 1.2f)); + liveLabelTextView.setScaleY(Math.max(0.9f, 1.0f - 0.1f * moveProgress * 1.2f)); + liveLabelTextView.setAlpha(Math.max(0.0f, 1.0f - moveProgress * 1.2f) * (1f - renderersContainer.progressToFullscreenMode)); } else { diff = 0; titleTextView.setScaleX(1.0f); titleTextView.setScaleY(1.0f); titleTextView.setAlpha(1f - renderersContainer.progressToFullscreenMode); + liveLabelTextView.setScaleX(1.0f); + liveLabelTextView.setScaleY(1.0f); + liveLabelTextView.setAlpha(1f - renderersContainer.progressToFullscreenMode); if (colorProgress > 0.0001f) { setColorProgress(0.0f); } } menuItemsContainer.setTranslationY(Math.max(AndroidUtilities.dp(4), scrollOffsetY - AndroidUtilities.dp(53) - diff)); - titleTextView.setTranslationY(Math.max(AndroidUtilities.dp(4), scrollOffsetY - AndroidUtilities.dp(44) - diff)); + titleLayout.setTranslationY(Math.max(AndroidUtilities.dp(4), scrollOffsetY - AndroidUtilities.dp(44) - diff)); + if (textureLightningView != null) { + textureLightningView.setTranslationY(Math.max(AndroidUtilities.dp(4), scrollOffsetY - AndroidUtilities.dp(37))); + } if (scheduleTimerContainer != null) { scheduleTimerContainer.setTranslationY(Math.max(AndroidUtilities.dp(4), scrollOffsetY - AndroidUtilities.dp(44) - diff)); } @@ -6405,6 +6613,64 @@ private void updateState(boolean animated, boolean selfUpdated) { soundButton.animate().scaleX(soundButtonScale).scaleY(soundButtonScale).setDuration(TRANSITION_DURATION).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } } + + updateLiveLabel(animated); + if (isRtmpStream() && LiteMode.isEnabled(LiteMode.FLAG_CALLS_ANIMATIONS)) { + if (currentCallState == VoIPService.STATE_ESTABLISHED) { + needTextureLightning = true; + runUpdateTextureLightningRunnable(); + } else { + needTextureLightning = false; + AndroidUtilities.cancelRunOnUIThread(updateTextureLightningRunnable); + } + } + } + + private void updateLiveLabel(boolean animated) { + if (isRtmpStream()) { + liveLabelTextView.setVisibility(View.VISIBLE); + boolean wasLive = ((int) liveLabelTextView.getTag()) == VoIPService.STATE_ESTABLISHED; + boolean isLive = currentCallState == VoIPService.STATE_ESTABLISHED; + liveLabelTextView.setTag(currentCallState); + if (wasLive != isLive) { + if (liveLabelBgColorAnimator != null) { + liveLabelBgColorAnimator.cancel(); + } + if (animated) { + int fromColor = liveLabelPaint.getColor(); + int toColor = isLive ? 0xffee3e4c : 0xff3d4657; + liveLabelBgColorAnimator = ValueAnimator.ofFloat(0f, 1f); + liveLabelBgColorAnimator.addUpdateListener(valueAnimator -> { + float progress = (float) valueAnimator.getAnimatedValue(); + int color = AndroidUtilities.getOffsetColor(fromColor, toColor, progress, 1f); + liveLabelPaint.setColor(color); + liveLabelTextView.invalidate(); + + textureLightningViewAnimatingAlpha = isLive ? progress : (1 - progress); + if (textureLightningView != null && needTextureLightning) { + textureLightningView.invalidate(); + } + }); + liveLabelBgColorAnimator.setDuration(300); + liveLabelBgColorAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + liveLabelBgColorAnimator.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationEnd(Animator animation) { + liveLabelBgColorAnimator = null; + liveLabelPaint.setColor(currentCallState == VoIPService.STATE_ESTABLISHED ? 0xffee3e4c : 0xff3d4657); + liveLabelTextView.invalidate(); + } + }); + liveLabelBgColorAnimator.start(); + } else { + liveLabelPaint.setColor(currentCallState == VoIPService.STATE_ESTABLISHED ? 0xffee3e4c : 0xff3d4657); + liveLabelTextView.invalidate(); + } + } + } else { + liveLabelTextView.setVisibility(View.GONE); + } } @Override @@ -6639,8 +6905,7 @@ private void updateMuteButton(int state, boolean animated) { if (changedSize) { expandSizeAnimator = ValueAnimator.ofFloat(0, 1); expandSizeAnimator.addUpdateListener(animation -> { - float multiplier = isLandscapeMode ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); - showView.setScaleX(multiplier); + float multiplier = isLandscapeMode || isRtmpStream() ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); showView.setScaleY(multiplier); }); expandSizeAnimator.addListener(new AnimatorListenerAdapter() { @@ -6651,8 +6916,7 @@ public void onAnimationEnd(Animator animation) { }); expandSizeAnimator.start(); } else { - float multiplier = isLandscapeMode ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); - + float multiplier = isLandscapeMode || isRtmpStream() ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); showView.setAlpha(1f); showView.setScaleX(multiplier); showView.setScaleY(multiplier); @@ -6664,7 +6928,7 @@ public void onAnimationEnd(Animator animation) { expandAnimator.addUpdateListener(animation -> { float val = (float) animation.getAnimatedValue(); - float multiplier = isLandscapeMode ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); + float multiplier = isLandscapeMode || isRtmpStream() ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); hideView.setAlpha(1f - val); float scale = (0.1f + (1f - val) * 0.9f) * multiplier; @@ -6684,7 +6948,7 @@ public void onAnimationEnd(Animator animation) { }); expandAnimator.start(); } else { - float multiplier = isLandscapeMode ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); + float multiplier = isLandscapeMode || isRtmpStream() ? muteButtonScale : AndroidUtilities.lerp(1f, muteButtonScale, renderersContainer.progressToFullscreenMode); showView.setAlpha(1f); showView.setScaleX(multiplier); @@ -6759,7 +7023,11 @@ public void onAnimationEnd(Animator animation) { } private void fillColors(int state, int[] colorsToSet) { - if (state == MUTE_BUTTON_STATE_UNMUTE) { + if (isRtmpStream()) { + colorsToSet[0] = Theme.getColor(Theme.key_voipgroup_disabledButton); + colorsToSet[1] = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_rtmpButton), Theme.getColor(Theme.key_voipgroup_soundButtonActiveScrolled), colorProgress, 1.0f); + colorsToSet[2] = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_listViewBackgroundUnscrolled), Theme.getColor(Theme.key_voipgroup_disabledButton), colorProgress, 1.0f); + } else if (state == MUTE_BUTTON_STATE_UNMUTE) { colorsToSet[0] = Theme.getColor(Theme.key_voipgroup_unmuteButton2); colorsToSet[1] = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_soundButtonActive), Theme.getColor(Theme.key_voipgroup_soundButtonActiveScrolled), colorProgress, 1.0f); colorsToSet[2] = Theme.getColor(Theme.key_voipgroup_soundButton); @@ -8727,4 +8995,99 @@ public boolean dispatchKeyEvent(@NonNull KeyEvent event) { } return super.dispatchKeyEvent(event); } + + public class WatchersView extends LinearLayout { + + private final AnimatedTextView watchersCountTextView; + private float lastWidth = 0; + + public WatchersView(Context context) { + super(context); + setOrientation(LinearLayout.VERTICAL); + setGravity(Gravity.CENTER); + watchersCountTextView = new AnimatedTextView(context, true, false, false); + watchersCountTextView.setTextColor(Color.WHITE); + watchersCountTextView.setTextSize(AndroidUtilities.dp(46)); + watchersCountTextView.setTypeface(AndroidUtilities.bold()); + watchersCountTextView.setGravity(Gravity.CENTER_HORIZONTAL); + + TextView labelTextView = new TextView(context); + labelTextView.setTextColor(Color.WHITE); + labelTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + labelTextView.setTypeface(AndroidUtilities.bold()); + labelTextView.setText(LocaleController.getString(R.string.VoipChannelWatching)); + + addView(watchersCountTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 46)); + addView(labelTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + } + + void setWatchersCount(int count) { + CharSequence watchersCountText = LocaleController.formatNumber(count, ','); + float newWidth = watchersCountTextView.getPaint().measureText(watchersCountText, 0, watchersCountText.length()); + if (lastWidth != newWidth) { + Shader watchersCountTextShader = new LinearGradient(0, 0, newWidth, 0, new int[]{getThemedColor(Theme.key_premiumGradient1), getThemedColor(Theme.key_premiumGradient3)}, new float[]{0.0f, 1.0f}, Shader.TileMode.CLAMP); + watchersCountTextView.getPaint().setShader(watchersCountTextShader); + lastWidth = newWidth; + } + watchersCountTextView.setText(watchersCountText); + } + } + + public class LightningView extends View { + private int[] currentColors; + private int parentBackgroundColor; + private final Paint paint; + private float shadowOffset; + + public LightningView(Context context) { + super(context); + + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setStyle(Paint.Style.FILL); + paint.setAlpha(0); + } + + @Override + protected void onDraw(@NonNull Canvas canvas) { + super.onDraw(canvas); + if (needTextureLightning && renderersContainer.progressToFullscreenMode < 0.1) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint); + } + } + + public void setNewColors(int[] colors) { + boolean needInvalidate = false; + if (currentColors == null || colors[0] != currentColors[0] || colors[1] != currentColors[1]) { + if (currentColors == null) { + paint.setAlpha(255); + } + currentColors = colors; + if (liveLabelBgColorAnimator != null && textureLightningViewAnimatingAlpha != 1) { + currentColors[0] = ColorUtils.setAlphaComponent(currentColors[0], (int) (255 * textureLightningViewAnimatingAlpha)); + currentColors[1] = ColorUtils.setAlphaComponent(currentColors[1], (int) (255 * textureLightningViewAnimatingAlpha)); + } + + LinearGradient gradient = new LinearGradient(0, 0, 0, textureLightningView.getMeasuredHeight(), currentColors, null, Shader.TileMode.CLAMP); + paint.setShader(gradient); + needInvalidate = true; + } + if (parentBackgroundColor != backgroundColor) { + paint.setShadowLayer(AndroidUtilities.dp(36), 0, shadowOffset, backgroundColor); + parentBackgroundColor = backgroundColor; + needInvalidate = true; + } + if (needInvalidate) { + invalidate(); + } + runUpdateTextureLightningRunnable(); + } + + public void setShadowOffset(int offset) { + if (shadowOffset != offset) { + paint.setShadowLayer(AndroidUtilities.dp(36), 0, shadowOffset, backgroundColor); + shadowOffset = offset; + invalidate(); + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ImageReceiverSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/ImageReceiverSpan.java index 50f3938030..abef4f2146 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ImageReceiverSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ImageReceiverSpan.java @@ -82,24 +82,31 @@ public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, return dp(sz); } + private boolean shadowEnabled = true; private float translateX, translateY; private int shadowPaintAlpha = 0xFF; @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { - if (shadowPaintAlpha != paint.getAlpha()) { + if (shadowEnabled && shadowPaintAlpha != paint.getAlpha()) { shadowPaint.setAlpha(shadowPaintAlpha = paint.getAlpha()); shadowPaint.setShadowLayer(dp(1), 0, dp(.66f), Theme.multAlpha(0x33000000, shadowPaintAlpha / 255f)); } final float l = translateX + x; final float t = translateY + (top + bottom) / 2f - dp(sz) / 2f; - AndroidUtilities.rectTmp.set(l, t, l + dp(sz), t + dp(sz)); - canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, shadowPaint); + if (shadowEnabled) { + AndroidUtilities.rectTmp.set(l, t, l + dp(sz), t + dp(sz)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, shadowPaint); + } imageReceiver.setImageCoords(l, t, dp(sz), dp(sz)); imageReceiver.setAlpha(paint.getAlpha() / 255f); imageReceiver.draw(canvas); } + public void enableShadow(boolean enable) { + shadowEnabled = enable; + } + public void translate(float x, float y) { this.translateX = x; this.translateY = y; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 0833de4857..0b35d2b124 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -36,6 +36,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Looper; import android.os.Parcelable; import android.os.StatFs; import android.os.StrictMode; @@ -116,6 +117,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.SharedPrefsHelper; import org.telegram.messenger.TopicsController; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; @@ -3098,11 +3100,21 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool } else if (open_settings == 7) { bulletinText = "Logs enabled."; ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE).edit().putBoolean("logsEnabled", BuildVars.LOGS_ENABLED = true).commit(); + Thread.setDefaultUncaughtExceptionHandler(BuildVars.LOGS_ENABLED ? (thread, exception) -> { + if (thread == Looper.getMainLooper().getThread()) { + FileLog.fatal(exception, true); + } + } : null); } else if (open_settings == 8) { ProfileActivity.sendLogs(LaunchActivity.this, false); } else if (open_settings == 9) { bulletinText = "Logs disabled."; ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE).edit().putBoolean("logsEnabled", BuildVars.LOGS_ENABLED = false).commit(); + Thread.setDefaultUncaughtExceptionHandler(BuildVars.LOGS_ENABLED ? (thread, exception) -> { + if (thread == Looper.getMainLooper().getThread()) { + FileLog.fatal(exception, true); + } + } : null); } if (bulletinText != null) { @@ -3564,7 +3576,16 @@ private String readImport(Uri uri) { try (ZipInputStream zis = new ZipInputStream(getContentResolver().openInputStream(uri))) { ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) { - if (zipEntry.getName().endsWith(".txt")) { + String name = zipEntry.getName(); + if (name == null) { + zipEntry = zis.getNextEntry(); + continue; + } + int idx = name.lastIndexOf("/"); + if (idx >= 0) { + name = name.substring(idx + 1); + } + if (name.endsWith(".txt")) { try { int linesCount = 0; BufferedReader r = new BufferedReader(new InputStreamReader(zis)); @@ -4083,6 +4104,8 @@ private void runLinkRequest(final int intentAccount, } else if (attachBot.request_write_access || forceNotInternalForApps) { AtomicBoolean allowWrite = new AtomicBoolean(true); AlertsCreator.createBotLaunchAlert(getLastFragment(), allowWrite, user, () -> { + SharedPrefsHelper.setWebViewConfirmShown(currentAccount, peerId, true); + attachBot.inactive = false; attachBot.request_write_access = !allowWrite.get(); @@ -4121,7 +4144,7 @@ private void runLinkRequest(final int intentAccount, if (botAppStartParam != null) { TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); if (user != null && user.bot) { - MessagesController.getInstance(intentAccount).openApp(null, user, 0, progress); + MessagesController.getInstance(intentAccount).openApp(null, user, botAppStartParam, 0, progress); } } else if (setAsAttachBot != null && attachMenuBotToOpen == null) { TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); @@ -4432,6 +4455,12 @@ public void didChangeOwner(TLRPC.User user) { } else { Bundle bundle = new Bundle(); bundle.putLong("chat_id", -dialog_id); + if (voicechat != null) { + bundle.putString("voicechat", voicechat); + } + if (videochat) { + bundle.putBoolean("videochat", true); + } presentFragment(TopicsFragment.getTopicsOrChat(this, bundle)); try { dismissLoading.run(); @@ -5185,6 +5214,7 @@ private void processWebAppBot(final int intentAccount, if (getBottomSheetTabs() != null && getBottomSheetTabs().tryReopenTab(props) != null) { return; } + SharedPrefsHelper.setWebViewConfirmShown(currentAccount, user.id, true); if (AndroidUtilities.isTablet()) { BotWebViewSheet sheet = new BotWebViewSheet(LaunchActivity.this, lastFragment != null ? lastFragment.getResourceProvider() : null); sheet.setWasOpenedByLinkIntent(openedTelegram); @@ -5908,6 +5938,20 @@ public boolean didSelectDialogs(DialogsActivity dialogsFragment, ArrayList arrayList = new ArrayList<>(); + arrayList.add(videoPath); + SendMessagesHelper.prepareSendingDocuments(accountInstance, arrayList, arrayList, null, captionToSend, null, did, replyToMsg, replyToMsg, null, null, null, notify, scheduleDate, null, null, 0, 0, false); + } else if (photoPathsArray != null && photoPathsArray.size() > 0 && !photosEditorOpened) { + if (sendingText != null && sendingText.length() <= 1024 && photoPathsArray.size() == 1) { + photoPathsArray.get(0).caption = sendingText; + sendingText = null; + } + SendMessagesHelper.prepareSendingMedia(accountInstance, photoPathsArray, did, replyToMsg, replyToMsg, null, null, false, false, null, notify, scheduleDate, 0, false, null, null, 0, 0, false); } } else { if (videoPath != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java index 496aed2dcd..5bd80c9c8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java @@ -38,6 +38,7 @@ import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; @@ -402,7 +403,7 @@ protected void onDraw(Canvas canvas) { subPriceView = new TextView(context); subPriceView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); subPriceView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3)); - subEditPriceCell = new EditTextCell(context, getString(getConnectionsManager().isTestBackend() ? R.string.RequireMonthlyFeePriceHintTest5Minutes : R.string.RequireMonthlyFeePriceHint), false, -1, resourceProvider) { + subEditPriceCell = new EditTextCell(context, getString(getConnectionsManager().isTestBackend() ? R.string.RequireMonthlyFeePriceHintTest5Minutes : R.string.RequireMonthlyFeePriceHint), false, false, -1, resourceProvider) { private boolean ignoreTextChanged; @Override protected void onTextChanged(CharSequence newText) { @@ -714,7 +715,7 @@ private void onCreateClicked(View view) { if (stars > 0) { req.flags |= 32; - req.subscription_pricing = new TLRPC.TL_starsSubscriptionPricing(); + req.subscription_pricing = new TL_stars.TL_starsSubscriptionPricing(); req.subscription_pricing.period = getConnectionsManager().isTestBackend() ? StarsController.PERIOD_5MINUTES : StarsController.PERIOD_MONTHLY; req.subscription_pricing.amount = stars; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java index 7d6b52e798..663d823efd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java @@ -38,6 +38,7 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; @@ -67,6 +68,7 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; @@ -952,6 +954,9 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat if (data.getData() != null) { String path = AndroidUtilities.getPath(data.getData()); if (path != null) { + if (path.startsWith("content://")) { + path = MediaController.copyFileToCache(data.getData(), "mp3"); + } File file = new File(path); if (chatAttachAlert.getDocumentLayout().isRingtone(file)) { apply = true; @@ -962,8 +967,13 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat } else if (data.getClipData() != null) { ClipData clipData = data.getClipData(); for (int i = 0; i < clipData.getItemCount(); i++) { - String path = clipData.getItemAt(i).getUri().toString(); - if (chatAttachAlert.getDocumentLayout().isRingtone(new File(path))) { + Uri uri = clipData.getItemAt(i).getUri(); + String path = uri.toString(); + if (path.startsWith("content://")) { + path = MediaController.copyFileToCache(uri, "mp3"); + } + final File file = new File(path); + if (chatAttachAlert.getDocumentLayout().isRingtone(file)) { apply = true; getMediaDataController().uploadRingtone(path); getNotificationCenter().postNotificationName(NotificationCenter.onUserRingtonesUpdated); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java index 09797c90b8..6d2af53f08 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java @@ -3855,8 +3855,8 @@ protected String doInBackground(Object... objects) { try { JSONObject jsonObject2 = new JSONObject(paymentForm.native_params.data); overrideSmartGlocalConnectionUrl = jsonObject2.getString("tokenize_url"); - if (overrideSmartGlocalConnectionUrl != null && ( - !overrideSmartGlocalConnectionUrl.startsWith("https://") || + if (overrideSmartGlocalConnectionUrl != null && !( + overrideSmartGlocalConnectionUrl.startsWith("https://") && overrideSmartGlocalConnectionUrl.endsWith(".smart-glocal.com/cds/v1/tokenize/card") )) { overrideSmartGlocalConnectionUrl = null; @@ -4245,9 +4245,6 @@ private void sendData() { paymentStatusSent = true; invoiceStatus = InvoiceStatus.PAID; - if (paymentFormCallback != null) { - paymentFormCallback.onInvoiceStatusChanged(invoiceStatus); - } onCheckoutSuccess(parentLayout, parentActivity); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 84a7d1bca1..98e17c787d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -146,6 +146,7 @@ import com.google.android.gms.vision.face.Face; import com.google.android.gms.vision.face.FaceDetector; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.ApplicationLoader; @@ -284,7 +285,6 @@ import java.io.FileOutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -809,6 +809,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { private OptionsSpeedIconDrawable menuItemIcon; private ActionBarMenuSubItem allMediaItem; private ActionBarMenuSubItem speedItem; + private ActionBarMenuSubItem qualityItem; private ActionBarPopupWindow.GapView speedGap; private ActionBarMenu menu; private ActionBarMenuItem sendItem; @@ -816,7 +817,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { private ActionBarMenuItem pipItem; private ActionBarMenuItem masksItem; private LinearLayout itemsLayout; - ChooseSpeedLayout chooseSpeedLayout; + private ChooseQualityLayout.QualityIcon qualityIcon; + private ChooseSpeedLayout chooseSpeedLayout; + private ChooseQualityLayout chooseQualityLayout; + private ChooseDownloadQualityLayout chooseDownloadQualityLayout; private Map actionBarItemsVisibility = new HashMap<>(3); private BackgroundDrawable backgroundDrawable = new BackgroundDrawable(0xff000000); private Paint blackPaint = new Paint(); @@ -1843,6 +1847,7 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b private boolean editing; private boolean fancyShadows; private MessageObject currentMessageObject; + private ArrayList currentPlayingVideoQualityFiles; private Uri currentPlayingVideoFile; private EditState editState = new EditState(); private TLRPC.BotInlineResult currentBotInlineResult; @@ -4133,10 +4138,10 @@ public void didReceivedNotification(int id, int account, Object... args) { if (loadInitialVideo) { loadInitialVideo = false; progressView.setVisibility(View.INVISIBLE); - preparePlayer(currentPlayingVideoFile, false, false, editState.savedFilterState); + preparePlayer(currentPlayingVideoQualityFiles, currentPlayingVideoFile, false, false, editState.savedFilterState); } else if (tryStartRequestPreviewOnFinish) { releasePlayer(false); - tryStartRequestPreviewOnFinish = !MediaController.getInstance().scheduleVideoConvert(videoPreviewMessageObject, true, true); + tryStartRequestPreviewOnFinish = !MediaController.getInstance().scheduleVideoConvert(videoPreviewMessageObject, true, true, false); } else if (messageObject == videoPreviewMessageObject) { requestingPreview = false; progressView.setVisibility(View.INVISIBLE); @@ -4152,7 +4157,7 @@ public void didReceivedNotification(int id, int account, Object... args) { requestingPreview = false; photoProgressViews[0].setProgress(1f, true); photoProgressViews[0].setBackgroundState(PROGRESS_PLAY, true, true); - preparePlayer(Uri.fromFile(new File(finalPath)), false, true, editState.savedFilterState); + preparePlayer(null, Uri.fromFile(new File(finalPath)), false, true, editState.savedFilterState); } } } else if (id == NotificationCenter.messagesDeleted) { @@ -4391,7 +4396,9 @@ public boolean dispatchTouchEvent(MotionEvent ev) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_POINTER_UP: - scheduleActionBarHide(); + if (currentMessageObject == null || !currentMessageObject.isSponsored()) { + scheduleActionBarHide(); + } break; } } @@ -5487,57 +5494,111 @@ public boolean canOpenMenu() { menuItem.setOnMenuDismiss(byClick -> checkProgress(0, false, false)); menuItem.getPopupLayout().swipeBackGravityRight = true; - chooseSpeedLayout = new ChooseSpeedLayout(activityContext, menuItem.getPopupLayout().getSwipeBack(), new ChooseSpeedLayout.Callback() { - @Override - public void onSpeedSelected(float speed, boolean isFinal, boolean closeMenu) { - if (speed != currentVideoSpeed) { - currentVideoSpeed = speed; - if (currentMessageObject != null) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("playback_speed", Activity.MODE_PRIVATE); - if (Math.abs(currentVideoSpeed - 1.0f) < 0.001f) { - preferences.edit().remove("speed" + currentMessageObject.getDialogId() + "_" + currentMessageObject.getId()).commit(); - } else { - preferences.edit().putFloat("speed" + currentMessageObject.getDialogId() + "_" + currentMessageObject.getId(), currentVideoSpeed).commit(); - } + chooseQualityLayout = new ChooseQualityLayout(activityContext, menuItem.getPopupLayout().getSwipeBack(), (qualityIndex, isFinal, closeMenu) -> { + if (videoPlayer != null) { + videoPlayer.setSelectedQuality(qualityIndex); + } + if (qualityIndex == VideoPlayer.QUALITY_AUTO) { + VideoPlayer.saveQuality(null, currentMessageObject); + } else { + VideoPlayer.saveQuality(videoPlayer.getQuality(qualityIndex), currentMessageObject); + } + updateQualityItems(); + if (closeMenu) { + menuItem.toggleSubMenu(); + } + }); + qualityItem = menuItem.addSwipeBackItem(0, qualityIcon = new ChooseQualityLayout.QualityIcon(activityContext), getString(R.string.Quality), chooseQualityLayout.layout); + qualityItem.setColors(0xfffafafa, 0xfffafafa); + qualityItem.setVisibility(View.GONE); + menuItem.getPopupLayout().getSwipeBack().addOnSwipeBackProgressListener((layout, to, t) -> { + qualityIcon.setRotation(t); + }); + chooseDownloadQualityLayout = new ChooseDownloadQualityLayout(activityContext, menuItem.getPopupLayout().getSwipeBack(), (messageObject, quality) -> { + if (quality == null) return; + TLRPC.Document document = quality.getDownloadDocument(); + if (document == null) return; + File f = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, false, true); + if (f == null || !f.exists()) { + f = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, true, true); + } + if (f != null && f.exists()) { + MediaController.saveFile(f.toString(), parentActivity, 1, null, null, uri -> BulletinFactory.createSaveToGalleryBulletin(containerView, true, 0xf9222222, 0xffffffff).show()); + } else { + ArrayList messageObjects = new ArrayList<>(); + messageObject.qualityToSave = document; + messageObjects.add(messageObject); + MediaController.saveFilesFromMessages(parentActivity, AccountInstance.getInstance(currentAccount), messageObjects, (count) -> { + if (parentActivity == null || containerView == null) { + return; } - if (videoPlayer != null) { - videoPlayer.setPlaybackSpeed(currentVideoSpeed); + if (count > 0) { + BulletinFactory.createSaveToGalleryBulletin(containerView, true, 0xf9222222, 0xffffffff).show(); } - if (photoViewerWebView != null) { - photoViewerWebView.setPlaybackSpeed(currentVideoSpeed); + }); + } + menuItem.toggleSubMenu(); + }); + + chooseSpeedLayout = new ChooseSpeedLayout(activityContext, menuItem.getPopupLayout().getSwipeBack(), (speed, isFinal, closeMenu) -> { + if (speed != currentVideoSpeed) { + currentVideoSpeed = speed; + if (currentMessageObject != null) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("playback_speed", Activity.MODE_PRIVATE); + if (Math.abs(currentVideoSpeed - 1.0f) < 0.001f) { + preferences.edit().remove("speed" + currentMessageObject.getDialogId() + "_" + currentMessageObject.getId()).commit(); + } else { + preferences.edit().putFloat("speed" + currentMessageObject.getDialogId() + "_" + currentMessageObject.getId(), currentVideoSpeed).commit(); } } - setMenuItemIcon(true, isFinal); - if (closeMenu) { - menuItem.toggleSubMenu(); + if (videoPlayer != null) { + videoPlayer.setPlaybackSpeed(currentVideoSpeed); + } + if (photoViewerWebView != null) { + photoViewerWebView.setPlaybackSpeed(currentVideoSpeed); } } + setMenuItemIcon(true, isFinal); + if (closeMenu) { + menuItem.toggleSubMenu(); + } }); - speedItem = menuItem.addSwipeBackItem(R.drawable.msg_speed, null, getString("Speed", R.string.Speed), chooseSpeedLayout.speedSwipeBackLayout); + speedItem = menuItem.addSwipeBackItem(R.drawable.msg_speed, null, getString(R.string.Speed), chooseSpeedLayout.speedSwipeBackLayout); menuItem.getPopupLayout().setSwipeBackForegroundColor(0xff222222); - speedItem.setSubtext(getString("SpeedNormal", R.string.SpeedNormal)); + speedItem.setSubtext(getString(R.string.SpeedNormal)); speedItem.setColors(0xfffafafa, 0xfffafafa); speedGap = menuItem.addColoredGap(); speedGap.setColor(0xff181818); menuItem.getPopupLayout().setFitItems(true); - menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); - menuItem.setContentDescription(getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, getString(R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); + menuItem.setContentDescription(getString(R.string.AccDescrMoreOptions)); allMediaItem = menuItem.addSubItem(gallery_menu_showall, R.drawable.msg_media, getString(R.string.ShowAllMedia)); allMediaItem.setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_savegif, R.drawable.msg_gif, getString("SaveToGIFs", R.string.SaveToGIFs)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_showinchat, R.drawable.msg_message, getString("ShowInChat", R.string.ShowInChat)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_save, R.drawable.msg_gallery, getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_savegif, R.drawable.msg_gif, getString(R.string.SaveToGIFs)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_showinchat, R.drawable.msg_message, getString(R.string.ShowInChat)).setColors(0xfffafafa, 0xfffafafa); + ActionBarMenuSubItem galleryButton = menuItem.addSwipeBackItem(R.drawable.msg_gallery, null, getString(R.string.SaveToGallery), chooseDownloadQualityLayout.layout).setColors(0xfffafafa, 0xfffafafa); + galleryButton.setRightIcon(0); + galleryButton.setOnClickListener(v -> { + if (currentMessageObject != null && currentMessageObject.hasVideoQualities() && chooseDownloadQualityLayout.update(currentMessageObject)) { + galleryButton.openSwipeBack(); + return; + } + if (actionBar != null && actionBar.getActionBarMenuOnItemClick() != null) { + actionBar.getActionBarMenuOnItemClick().onItemClick(gallery_menu_save); + menuItem.toggleSubMenu(); + } + }); menuItem.addSubItem(gallery_menu_reply, R.drawable.menu_reply, getString(R.string.Reply)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_share, R.drawable.msg_shareout, getString("ShareFile", R.string.ShareFile)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_masks2, R.drawable.msg_sticker, getString("ShowStickers", R.string.ShowStickers)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_share, R.drawable.msg_shareout, getString(R.string.ShareFile)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_masks2, R.drawable.msg_sticker, getString(R.string.ShowStickers)).setColors(0xfffafafa, 0xfffafafa); //menuItem.addSubItem(gallery_menu_edit_avatar, R.drawable.photo_paint, LocaleController.getString(R.string.EditPhoto)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_set_as_main, R.drawable.msg_openprofile, getString("SetAsMain", R.string.SetAsMain)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_set_as_main, R.drawable.msg_openprofile, getString(R.string.SetAsMain)).setColors(0xfffafafa, 0xfffafafa); menuItem.addSubItem(gallery_menu_translate, R.drawable.msg_translate, getString(R.string.TranslateMessage)).setColors(0xfffafafa, 0xfffafafa); menuItem.addSubItem(gallery_menu_hide_translation, R.drawable.msg_translate, getString(R.string.HideTranslation)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_delete, R.drawable.msg_delete, getString("Delete", R.string.Delete)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.msg_cancel, getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_delete, R.drawable.msg_delete, getString(R.string.Delete)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.msg_cancel, getString(R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa); menuItem.redrawPopup(0xf9222222); menuItem.hideSubItem(gallery_menu_translate); menuItem.hideSubItem(gallery_menu_hide_translation); @@ -7521,22 +7582,61 @@ private void setMenuItemIcon(boolean animated, boolean isFinal) { menuItemIcon.setSpeed(Math.abs(currentVideoSpeed - 1f) < 0.001f ? null : currentVideoSpeed, animated); if (isFinal) { if (Math.abs(currentVideoSpeed - 0.2f) < 0.05f) { - speedItem.setSubtext(getString("VideoSpeedVerySlow", R.string.VideoSpeedVerySlow)); + speedItem.setSubtext(getString(R.string.VideoSpeedVerySlow)); } else if (Math.abs(currentVideoSpeed - 0.5f) < 0.05f) { - speedItem.setSubtext(getString("VideoSpeedSlow", R.string.VideoSpeedSlow)); + speedItem.setSubtext(getString(R.string.VideoSpeedSlow)); } else if (Math.abs(currentVideoSpeed - 1.0f) < 0.05f) { - speedItem.setSubtext(getString("VideoSpeedNormal", R.string.VideoSpeedNormal)); + speedItem.setSubtext(getString(R.string.VideoSpeedNormal)); } else if (Math.abs(currentVideoSpeed - 1.5f) < 0.05f) { - speedItem.setSubtext(getString("VideoSpeedFast", R.string.VideoSpeedFast)); + speedItem.setSubtext(getString(R.string.VideoSpeedFast)); } else if (Math.abs(currentVideoSpeed - 2f) < 0.05f) { - speedItem.setSubtext(getString("VideoSpeedVeryFast", R.string.VideoSpeedVeryFast)); + speedItem.setSubtext(getString(R.string.VideoSpeedVeryFast)); } else { - speedItem.setSubtext(LocaleController.formatString("VideoSpeedCustom", R.string.VideoSpeedCustom, SpeedIconDrawable.formatNumber(currentVideoSpeed) + "x")); + speedItem.setSubtext(LocaleController.formatString(R.string.VideoSpeedCustom, SpeedIconDrawable.formatNumber(currentVideoSpeed) + "x")); } } chooseSpeedLayout.update(currentVideoSpeed, isFinal); } + private void updateQualityItems() { + if (chooseQualityLayout == null || qualityItem == null) return; + if (chooseQualityLayout.update(videoPlayer)) { + qualityItem.setVisibility(View.VISIBLE); + if (videoPlayer.getSelectedQuality() == VideoPlayer.QUALITY_AUTO) { + qualityItem.setSubtext(getString(R.string.QualityAuto)); + } else { + final VideoPlayer.Quality q = videoPlayer.getQuality(videoPlayer.getSelectedQuality()); + qualityItem.setSubtext(q != null ? Math.min(q.width, q.height) + "p" : ""); + } + final VideoPlayer.Quality q = videoPlayer.getCurrentQuality(); + if (q != null) { + final int max = Math.max(q.width, q.height); + int p = Math.min(q.width, q.height); + if (Math.abs(p - 1080) < 30) p = 1080; + else if (Math.abs(p - 720) < 30) p = 720; + else if (Math.abs(p - 360) < 30) p = 360; + else if (Math.abs(p - 240) < 30) p = 240; + else if (Math.abs(p - 144) < 30) p = 144; + if (max >= 16000) { + qualityIcon.text.setText("16K"); + } else if (max >= 8000) { + qualityIcon.text.setText("8K"); + } else if (max >= 4000) { + qualityIcon.text.setText("4K"); + } else if (p >= 1080) { + qualityIcon.text.setText("HD"); + } else { + qualityIcon.text.setText(p + ""); + } + } else { + qualityIcon.text.setText(""); + } + } else { + qualityItem.setVisibility(View.GONE); + qualityIcon.text.setText(""); + } + } + public float getCurrentVideoSpeed() { return currentVideoSpeed; } @@ -8630,7 +8730,7 @@ private VideoEditedInfo getCurrentVideoEditedInfo() { videoEditedInfo.avatarStartTime = 0; return videoEditedInfo; } - if (!isCurrentVideo || currentPlayingVideoFile == null || compressionsCount == 0) { + if (!isCurrentVideo || currentPlayingVideoFile == null && currentPlayingVideoQualityFiles == null || compressionsCount == 0) { return null; } VideoEditedInfo videoEditedInfo = new VideoEditedInfo(); @@ -8947,7 +9047,7 @@ private void scheduleActionBarHide() { } private void scheduleActionBarHide(int delay) { - if (!isAccessibilityEnabled()) { + if (!isAccessibilityEnabled() && !(currentMessageObject != null && currentMessageObject.isSponsored())) { AndroidUtilities.cancelRunOnUIThread(hideActionBarRunnable); AndroidUtilities.runOnUIThread(hideActionBarRunnable, delay); } @@ -9163,13 +9263,14 @@ private void seekVideoOrWebToProgress(float progress) { } } - private void preparePlayer(Uri uri, boolean playWhenReady, boolean preview) { - preparePlayer(uri, playWhenReady, preview, null); + private void preparePlayer(ArrayList videoUrises, Uri uri, boolean playWhenReady, boolean preview) { + preparePlayer(videoUrises, uri, playWhenReady, preview, null); } - private void preparePlayer(Uri uri, boolean playWhenReady, boolean preview, MediaController.SavedFilterState savedFilterState) { + private void preparePlayer(ArrayList videoUrises, Uri uri, boolean playWhenReady, boolean preview, MediaController.SavedFilterState savedFilterState) { if (!preview) { currentPlayingVideoFile = uri; + currentPlayingVideoQualityFiles = videoUrises; } if (parentActivity == null) { return; @@ -9278,8 +9379,10 @@ public void onRenderedFirstFrame() { if (usedSurfaceView) { containerView.invalidate(); } + updateQualityItems(); } }; + videoPlayer.setOnQualityChangeListener(this::updateQualityItems); newPlayerCreated = true; } if (videoTextureView != null) { @@ -9472,7 +9575,12 @@ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } } - videoPlayer.preparePlayer(uri, "other"); + if (videoUrises != null) { + videoPlayer.preparePlayer(videoUrises, VideoPlayer.getSavedQuality(videoUrises, currentMessageObject)); + } else { + videoPlayer.preparePlayer(uri, "other"); + } + updateQualityItems(); videoPlayer.setPlayWhenReady(playWhenReady); } @@ -9512,7 +9620,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } public void checkFullscreenButton() { - if (imagesArr.isEmpty()) { + if (imagesArr.isEmpty() || currentMessageObject != null && currentMessageObject.isSponsored()) { for (int b = 0; b < 3; b++) { fullscreenButton[b].setVisibility(View.INVISIBLE); } @@ -12552,6 +12660,7 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca menuItem.hideSubItem(gallery_menu_delete); speedItem.setVisibility(View.GONE); speedGap.setVisibility(View.GONE); + qualityItem.setVisibility(View.GONE); actionBar.setTranslationY(0); dialogPhotos = null; @@ -13136,6 +13245,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated menuItem.checkHideMenuItem(); } else { speedItem.setVisibility(View.GONE); + qualityItem.setVisibility(View.GONE); speedGap.setVisibility(View.GONE); menuItem.hideSubItem(gallery_menu_openin); menuItem.checkHideMenuItem(); @@ -14031,6 +14141,9 @@ private void setImageIndex(int index, boolean init, boolean animateCaption) { } currentMessageObject = newMessageObject; isVideo = newMessageObject.isVideo(); + if (newMessageObject.isSponsored()) { + AndroidUtilities.cancelRunOnUIThread(hideActionBarRunnable); + } if (sharedMediaType == MediaDataController.MEDIA_FILE) { if (canZoom = newMessageObject.canPreviewDocument()) { if (allowShare) { @@ -14053,6 +14166,7 @@ private void setImageIndex(int index, boolean init, boolean animateCaption) { speedGap.setVisibility(View.GONE); menuItem.checkHideMenuItem(); } + updateQualityItems(); } else if (!secureDocuments.isEmpty()) { if (index < 0 || index >= secureDocuments.size()) { closePhoto(false, false); @@ -14240,7 +14354,7 @@ private void setImageIndex(int index, boolean init, boolean animateCaption) { } if (isVideo && videoPath != null) { isStreaming = false; - preparePlayer(videoPath, sendPhotoType == SELECT_TYPE_AVATAR, false, editState.savedFilterState); + preparePlayer(null, videoPath, sendPhotoType == SELECT_TYPE_AVATAR, false, editState.savedFilterState); } if (!imagesArrLocals.isEmpty()) { @@ -18560,6 +18674,7 @@ private void onActionClick(boolean download) { if (currentMessageObject == null && currentBotInlineResult == null && (pageBlocksAdapter == null || currentFileNames[0] == null) && sendPhotoType != SELECT_TYPE_NO_SELECT) { return; } + ArrayList videoUrises = null; Uri uri = null; File file = null; isStreaming = false; @@ -18571,29 +18686,26 @@ private void onActionClick(boolean download) { } } if (file == null) { - file = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); - if (!file.exists()) { + final TLRPC.Document original; + final ArrayList alt_documents = new ArrayList<>(); + if (currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.media != null && currentMessageObject.messageOwner.media.document != null) { + original = currentMessageObject.messageOwner.media.document; + alt_documents.addAll(currentMessageObject.messageOwner.media.alt_documents); + } else { + original = currentMessageObject.getDocument(); + } + if ((original != null ? 1 : 0) + alt_documents.size() <= 1) { + file = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); + } + if (file == null || !file.exists()) { file = null; if (SharedConfig.streamMedia && !DialogObject.isEncryptedDialog(currentMessageObject.getDialogId()) && currentMessageObject.isVideo() && currentMessageObject.canStreamVideo()) { - try { - int reference = FileLoader.getInstance(currentMessageObject.currentAccount).getFileReference(currentMessageObject); - FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_NORMAL, 0); - TLRPC.Document document = currentMessageObject.getDocument(); - String params = "?account=" + currentMessageObject.currentAccount + - "&id=" + document.id + - "&hash=" + document.access_hash + - "&dc=" + document.dc_id + - "&size=" + document.size + - "&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") + - "&rid=" + reference + - "&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") + - "&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]); - uri = Uri.parse("tg://" + currentMessageObject.getFileName() + params); - isStreaming = true; - checkProgress(0, false, false); - } catch (Exception ignore) { + final int reference = FileLoader.getInstance(currentMessageObject.currentAccount).getFileReference(currentMessageObject); - } + videoUrises = new ArrayList<>(); + videoUrises.addAll(VideoPlayer.getQualities(currentAccount, original, alt_documents, reference, false)); + isStreaming = true; + checkProgress(0, false, false); } } } @@ -18627,10 +18739,10 @@ private void onActionClick(boolean download) { } } } - if (file != null && uri == null) { + if (file != null && uri == null && videoUrises == null) { uri = Uri.fromFile(file); } - if (uri == null) { + if (uri == null && videoUrises == null) { if (download) { if (currentMessageObject != null) { if (!FileLoader.getInstance(currentAccount).isLoadingFile(currentFileNames[0])) { @@ -18669,7 +18781,7 @@ private void onActionClick(boolean download) { AndroidUtilities.openDocument(currentMessageObject, parentActivity, null); return; } - preparePlayer(uri, true, false); + preparePlayer(videoUrises, uri, true, false); videoSizeSet = true; } } @@ -18810,6 +18922,19 @@ public boolean onSingleTapConfirmed(MotionEvent e) { } } } + if (currentMessageObject != null && currentMessageObject.isSponsored()) { + if (x >= (getContainerViewWidth() - centerImage.getImageWidth()) / 2.0f && x <= (getContainerViewWidth() + centerImage.getImageWidth()) / 2.0f && + y >= (getContainerViewHeight() - centerImage.getImageHeight()) / 2.0f && y <= (getContainerViewHeight() + centerImage.getImageHeight()) / 2.0f) { + if (parentFragment instanceof ChatActivity) { + ((ChatActivity) parentFragment).logSponsoredClicked(currentMessageObject, true, true); + } + closePhoto(true, false); + if (currentMessageObject.sponsoredUrl != null) { + Browser.openUrl(LaunchActivity.instance != null ? LaunchActivity.instance : activityContext, Uri.parse(currentMessageObject.sponsoredUrl), true, false, false, null, null, false, MessagesController.getInstance(currentAccount).sponsoredLinksInappAllow); + } + return true; + } + } if (photoViewerWebView != null && photoViewerWebView.isControllable() && isActionBarVisible) { View v = photoViewerWebView.getWebView(); @@ -18860,7 +18985,7 @@ public boolean onSingleTapConfirmed(MotionEvent e) { } } } - if (photoViewerWebView == null || !photoViewerWebView.isControllable() || photoViewerWebView.isPlaying() || !isActionBarVisible) { + if ((photoViewerWebView == null || !photoViewerWebView.isControllable() || photoViewerWebView.isPlaying() || !isActionBarVisible) && !(currentMessageObject != null && currentMessageObject.isSponsored())) { toggleActionBar(!isActionBarVisible, true); } } else if (sendPhotoType == 0 || sendPhotoType == 4) { @@ -19282,7 +19407,7 @@ private void requestVideoPreview(int request) { photoProgressViews[0].setProgress(0,photoProgressViews[0].backgroundState == 0 || photoProgressViews[0].previousBackgroundState == 0); photoProgressViews[0].setBackgroundState(PROGRESS_PLAY, false, true); if (!wasRequestingPreview) { - preparePlayer(currentPlayingVideoFile, false, false, editState.savedFilterState); + preparePlayer(currentPlayingVideoQualityFiles, currentPlayingVideoFile, false, false, editState.savedFilterState); videoPlayer.seekTo((long) (videoTimelineView.getLeftProgress() * videoDuration)); } else { loadInitialVideo = true; @@ -19303,7 +19428,12 @@ private void requestVideoPreview(int request) { videoPreviewMessageObject.videoEditedInfo.originalWidth = originalWidth; videoPreviewMessageObject.videoEditedInfo.originalHeight = originalHeight; videoPreviewMessageObject.videoEditedInfo.framerate = videoFramerate; - videoPreviewMessageObject.videoEditedInfo.originalPath = currentPlayingVideoFile.getPath(); + if (currentPlayingVideoFile == null) { + // TODO + videoPreviewMessageObject.videoEditedInfo.originalPath = currentPlayingVideoFile.getPath(); + } else { + videoPreviewMessageObject.videoEditedInfo.originalPath = currentPlayingVideoFile.getPath(); + } } long start = videoPreviewMessageObject.videoEditedInfo.startTime = startTime; long end = videoPreviewMessageObject.videoEditedInfo.endTime = endTime; @@ -19322,7 +19452,7 @@ private void requestVideoPreview(int request) { videoPreviewMessageObject.videoEditedInfo.needUpdateProgress = true; videoPreviewMessageObject.videoEditedInfo.originalDuration = (long) (videoDuration * 1000); - if (!MediaController.getInstance().scheduleVideoConvert(videoPreviewMessageObject, true, true)) { + if (!MediaController.getInstance().scheduleVideoConvert(videoPreviewMessageObject, true, true, true)) { tryStartRequestPreviewOnFinish = true; } requestingPreview = true; @@ -19334,7 +19464,7 @@ private void requestVideoPreview(int request) { tryStartRequestPreviewOnFinish = false; photoProgressViews[0].setBackgroundState(PROGRESS_PLAY, false, true); if (request == 2) { - preparePlayer(currentPlayingVideoFile, false, false, editState.savedFilterState); + preparePlayer(currentPlayingVideoQualityFiles, currentPlayingVideoFile, false, false, editState.savedFilterState); videoPlayer.seekTo((long) (videoTimelineView.getLeftProgress() * videoDuration)); } } @@ -19371,6 +19501,10 @@ private Size calculateResultVideoSize() { resultWidth = Math.round(originalWidth * scale / 2) * 2; resultHeight = Math.round(originalHeight * scale / 2) * 2; } + if (resultWidth % 4 != 0 || resultHeight % 4 != 0) { + resultWidth -= resultWidth % 4; + resultWidth -= resultHeight % 4; + } return new Size(resultWidth, resultHeight); } @@ -20850,7 +20984,7 @@ public void openAdsMenu() { if (currentMessageObject.sponsoredUrl != null && !TextUtils.equals(AndroidUtilities.getHostAuthority(currentMessageObject.sponsoredUrl), MessagesController.getInstance(currentAccount).linkPrefix)) { TextView textView = new TextView(activityContext); - textView.setTextColor(getThemedColor(Theme.key_chat_messageLinkIn)); + textView.setTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); 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)); @@ -20863,7 +20997,7 @@ public void openAdsMenu() { } o.dismiss(); if (parentFragment instanceof ChatActivity) { - ((ChatActivity) parentFragment).logSponsoredClicked(currentMessageObject); + ((ChatActivity) parentFragment).logSponsoredClicked(currentMessageObject, false, true); } Browser.openUrl(activityContext, Uri.parse(currentMessageObject.sponsoredUrl), true, false, false, null, null, false, MessagesController.getInstance(currentAccount).sponsoredLinksInappAllow); }); @@ -20881,7 +21015,7 @@ public void openAdsMenu() { if (currentMessageObject.sponsoredInfo != null) { TextView textView = new TextView(activityContext); - textView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); + textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourcesProvider)); 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)); @@ -20897,7 +21031,7 @@ public void openAdsMenu() { if (currentMessageObject.sponsoredAdditionalInfo != null) { TextView textView = new TextView(activityContext); - textView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); + textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourcesProvider)); 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)); @@ -20915,7 +21049,7 @@ public void openAdsMenu() { View section = sections.get(i); if (i > 0) { FrameLayout separator = new FrameLayout(activityContext); - separator.setBackgroundColor(getThemedColor(Theme.key_divider)); + separator.setBackgroundColor(Theme.getColor(Theme.key_divider, resourcesProvider)); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 1); params.height = 1; info.addView(separator, params); @@ -21020,7 +21154,7 @@ private void createAdButtonView() { adButtonView.setOnClickListener(v -> { if (currentMessageObject == null || !currentMessageObject.isSponsored()) return; if (parentFragment instanceof ChatActivity) { - ((ChatActivity) parentFragment).logSponsoredClicked(currentMessageObject); + ((ChatActivity) parentFragment).logSponsoredClicked(currentMessageObject, false, true); } closePhoto(true, false); if (currentMessageObject.sponsoredUrl != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 7319380de4..ddb1130d69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -1341,7 +1341,9 @@ private void updateSubtitle() { } else { nameTextView.setText(UserObject.getUserName(currentUser)); } - if (currentUser != null && currentUser.id == 777000) { + if (currentUser != null && currentUser.id == UserObject.VERIFY) { + onlineTextView.setText(LocaleController.getString(R.string.VerifyCodesNotifications)); + } else if (currentUser != null && currentUser.id == 777000) { onlineTextView.setText(LocaleController.getString(R.string.ServiceNotifications)); } else { CharSequence printString = MessagesController.getInstance(currentMessageObject.currentAccount).getPrintingString(currentMessageObject.getDialogId(), 0, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 04d551065c..6109682873 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -61,6 +61,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Looper; import android.os.SystemClock; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -233,14 +234,11 @@ import org.telegram.ui.Components.MediaActivity; import org.telegram.ui.Components.MessagePrivateSeenView; import org.telegram.ui.Components.Paint.PersistColorPalette; -import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; import org.telegram.ui.Components.Premium.ProfilePremiumCell; -import org.telegram.ui.Components.Premium.boosts.BoostRepository; -import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftToUsersBottomSheet; import org.telegram.ui.Components.Premium.boosts.UserSelectorBottomSheet; import org.telegram.ui.Components.ProfileGalleryView; import org.telegram.ui.Components.RLottieDrawable; @@ -259,6 +257,7 @@ import org.telegram.ui.Components.UndoView; import org.telegram.ui.Components.VectorAvatarThumbDrawable; import org.telegram.ui.Components.voip.VoIPHelper; +import org.telegram.ui.Gifts.GiftSheet; import org.telegram.ui.Stars.BotStarsActivity; import org.telegram.ui.Stars.BotStarsController; import org.telegram.ui.Stars.StarsController; @@ -327,7 +326,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private ScamDrawable scamDrawable; private UndoView undoView; private OverlaysView overlaysView; - private SharedMediaLayout sharedMediaLayout; + public SharedMediaLayout sharedMediaLayout; private StickerEmptyView emptyView; private boolean sharedMediaLayoutAttached; private SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader; @@ -417,6 +416,7 @@ public void setAlpha(int a) { private boolean isTopic; private boolean openSimilar; public boolean myProfile; + public boolean openGifts; private boolean scrolling; @@ -652,6 +652,7 @@ public void setAlpha(int a) { private String vcardFirstName; private String vcardLastName; + BaseFragment previousTransitionMainFragment; ChatActivityInterface previousTransitionFragment; HashSet notificationsExceptionTopics = new HashSet<>(); @@ -1031,6 +1032,9 @@ protected void onDraw(Canvas canvas) { if (previousTransitionFragment.getActionBar() != null && !previousTransitionFragment.getContentView().blurWasDrawn() && previousTransitionFragment.getActionBar().getBackground() == null) { paint.setColor(Theme.getColor(Theme.key_actionBarDefault, previousTransitionFragment.getResourceProvider())); canvas.drawRect(blurBounds, paint); + } else if (previousTransitionMainFragment != null && previousTransitionMainFragment instanceof DialogsActivity && previousTransitionMainFragment.getFragmentView() instanceof SizeNotifierFrameLayout) { + previousTransitionMainFragment.getActionBar().blurScrimPaint.setColor(Theme.getColor(Theme.key_actionBarDefault, previousTransitionMainFragment.getResourceProvider())); + ((SizeNotifierFrameLayout) previousTransitionMainFragment.getFragmentView()).drawBlurRect(canvas, getY(), blurBounds, previousTransitionMainFragment.getActionBar().blurScrimPaint, true); } else { previousTransitionFragment.getContentView().drawBlurRect(canvas, getY(), blurBounds, previousTransitionFragment.getActionBar().blurScrimPaint, true); } @@ -1782,6 +1786,7 @@ public boolean onFragmentCreate() { vcardLastName = arguments.getString("vcard_last_name"); reportSpam = arguments.getBoolean("reportSpam", false); myProfile = arguments.getBoolean("my_profile", false); + openGifts = arguments.getBoolean("open_gifts", false); if (!expandPhoto) { expandPhoto = arguments.getBoolean("expandPhoto", false); if (expandPhoto) { @@ -2283,7 +2288,7 @@ public void onClick(DialogInterface dialog, int which) { button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); } } else if (id == report) { - AlertsCreator.createReportAlert(getParentActivity(), getDialogId(), 0, 0, ProfileActivity.this, resourcesProvider, null); + ReportBottomSheet.openChat(ProfileActivity.this, getDialogId()); } else if (id == edit_channel) { if (isTopic) { Bundle args = new Bundle(); @@ -2447,7 +2452,7 @@ public void didChangeOwner(TLRPC.User user) { } else if (id == view_discussion) { openDiscussion(); } else if (id == gift_premium) { - showDialog(new GiftPremiumBottomSheet(ProfileActivity.this, getMessagesController().getUser(userId))); + showDialog(new GiftSheet(getContext(), currentAccount, userId, null, null)); } else if (id == channel_stories) { Bundle args = new Bundle(); args.putInt("type", MediaActivity.TYPE_ARCHIVED_CHANNEL_STORIES); @@ -3125,8 +3130,133 @@ protected void onDetachedFromWindow() { } }; - ArrayList users = chatInfo != null && chatInfo.participants != null && chatInfo.participants.participants.size() > 5 ? sortedUsers : null; - sharedMediaLayout = new SharedMediaLayout(context, did, sharedMediaPreloader, userInfo != null ? userInfo.common_chats_count : 0, sortedUsers, chatInfo, userInfo, openSimilar ? SharedMediaLayout.TAB_RECOMMENDED_CHANNELS : users != null ? SharedMediaLayout.TAB_GROUPUSERS : -1, this, this, SharedMediaLayout.VIEW_TYPE_PROFILE_ACTIVITY, resourcesProvider) { + if (myProfile) { + bottomButtonsContainer = new FrameLayout(context); + + 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)); + } + } + } + + final ArrayList users = chatInfo != null && chatInfo.participants != null && chatInfo.participants.participants.size() > 5 ? sortedUsers : null; + int initialTab = -1; + if (openGifts && userInfo != null && userInfo.stargifts_count > 0) initialTab = SharedMediaLayout.TAB_GIFTS; + else if (openSimilar) initialTab = SharedMediaLayout.TAB_RECOMMENDED_CHANNELS; + else if (users != null) initialTab = SharedMediaLayout.TAB_GROUPUSERS; + sharedMediaLayout = new SharedMediaLayout(context, did, sharedMediaPreloader, userInfo != null ? userInfo.common_chats_count : 0, sortedUsers, chatInfo, userInfo, initialTab, this, this, SharedMediaLayout.VIEW_TYPE_PROFILE_ACTIVITY, resourcesProvider) { @Override protected int processColor(int color) { return applyPeerColor(color, false); @@ -3211,8 +3341,11 @@ protected void showActionMode(boolean show) { 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()); + int width = sharedMediaLayout == null ? AndroidUtilities.displaySize.x : sharedMediaLayout.getMeasuredWidth(); + if (bottomButtonContainer[0] != null) + bottomButtonContainer[0].setTranslationX((SharedMediaLayout.TAB_STORIES - progress) * width); + if (bottomButtonContainer[1] != null) + bottomButtonContainer[1].setTranslationX((SharedMediaLayout.TAB_ARCHIVED_STORIES - progress) * width); updateBottomButtonY(); } } @@ -3781,7 +3914,7 @@ public void openExceptions() { } else if (position == sendMessageRow) { onWriteButtonClick(); } else if (position == reportRow) { - AlertsCreator.createReportAlert(getParentActivity(), getDialogId(), 0, 0, ProfileActivity.this, resourcesProvider, null); + ReportBottomSheet.openChat(ProfileActivity.this, getDialogId()); } else if (position >= membersStartRow && position < membersEndRow) { TLRPC.ChatParticipant participant; if (!sortedUsers.isEmpty()) { @@ -3995,8 +4128,8 @@ public boolean onItemClick(View view, int position) { BuildVars.DEBUG_VERSION ? "Clear bot biometry data" : null, BuildVars.DEBUG_PRIVATE_VERSION ? "Clear all login tokens" : null, SharedConfig.canBlurChat() && Build.VERSION.SDK_INT >= 31 ? (SharedConfig.useNewBlur ? "back to cpu blur" : "use new gpu blur") : null, - BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.botTabs3DEffect ? "disable tabs 3d effect" : "enable tabs 3d effect") : null, - SharedConfig.adaptableColorInBrowser ? "Disabled adaptive browser colors" : "Enable adaptive browser colors" + SharedConfig.adaptableColorInBrowser ? "Disabled adaptive browser colors" : "Enable adaptive browser colors", + SharedConfig.debugVideoQualities ? "Disable video qualities debug" : "Enable video qualities debug" }; builder.setItems(items, (dialog, which) -> { @@ -4012,6 +4145,11 @@ public boolean onItemClick(View view, int position) { getMessagesController().forceResetDialogs(); } else if (which == 4) { // Logs BuildVars.LOGS_ENABLED = !BuildVars.LOGS_ENABLED; + Thread.setDefaultUncaughtExceptionHandler(BuildVars.LOGS_ENABLED ? (thread, exception) -> { + if (thread == Looper.getMainLooper().getThread()) { + FileLog.fatal(exception, true); + } + } : null); SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE); sharedPreferences.edit().putBoolean("logsEnabled", BuildVars.LOGS_ENABLED).commit(); updateRowsIds(); @@ -4269,9 +4407,9 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo } else if (which == 31) { SharedConfig.toggleUseNewBlur(); } else if (which == 32) { - SharedConfig.setBotTabs3DEffect(!SharedConfig.botTabs3DEffect); - } else if (which == 33) { SharedConfig.toggleBrowserAdaptableColors(); + } else if (which == 33) { + SharedConfig.toggleDebugVideoQualities(); } }); builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); @@ -5074,125 +5212,7 @@ public void setAlpha(float alpha) { 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; @@ -5202,7 +5222,7 @@ private void updateBottomButtonY() { if (bottomButtonsContainer == null) { return; } - bottomButtonsContainer.setTranslationY(sharedMediaLayout.isAttachedToWindow() ? Math.max(0, dp(72 + 64 + 48) - (listView.getMeasuredHeight() - sharedMediaLayout.getY())) : dp(72)); + bottomButtonsContainer.setTranslationY(sharedMediaLayout != null && sharedMediaLayout.isAttachedToWindow() ? Math.max(0, dp(72 + 64 + 48) - (listView.getMeasuredHeight() - sharedMediaLayout.getY())) : dp(72)); Bulletin bulletin = Bulletin.getVisibleBulletin(); if (bulletin != null) { bulletin.updatePosition(); @@ -6954,6 +6974,8 @@ public void updateSelectedMediaTabText() { } else if (id == SharedMediaLayout.TAB_SAVED_MESSAGES) { int messagesCount = getMessagesController().getSavedMessagesController().getMessagesCount(getDialogId()); mediaCounterTextView.setText(LocaleController.formatPluralString("SavedMessagesCount", Math.max(1, messagesCount))); + } else if (id == SharedMediaLayout.TAB_GIFTS) { + mediaCounterTextView.setText(LocaleController.formatPluralStringComma("ProfileGiftsCount", sharedMediaLayout.giftsContainer.getGiftsCount())); } } @@ -7743,8 +7765,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else if (id == NotificationCenter.newSuggestionsAvailable) { int prevRow1 = passwordSuggestionRow; int prevRow2 = phoneSuggestionRow; + int prevRow3 = graceSuggestionRow; updateRowsIds(); - if (prevRow1 != passwordSuggestionRow || prevRow2 != phoneSuggestionRow) { + if (prevRow1 != passwordSuggestionRow || prevRow2 != phoneSuggestionRow || prevRow3 != graceSuggestionRow) { listAdapter.notifyDataSetChanged(); } } else if (id == NotificationCenter.topicsDidLoaded) { @@ -7946,7 +7969,7 @@ public boolean isSwipeBackEnabled(MotionEvent event) { return false; } sharedMediaLayout.getHitRect(rect); - if (!rect.contains((int) event.getX(), (int) event.getY() - actionBar.getMeasuredHeight())) { + if (event != null && !rect.contains((int) event.getX(), (int) event.getY() - actionBar.getMeasuredHeight())) { return true; } return sharedMediaLayout.isCurrentTabFirst(); @@ -8165,6 +8188,7 @@ public AnimatorSet onCustomTransitionAnimation(final boolean isOpen, final Runna starBgItem.setScaleX(1.0f); starBgItem.setScaleY(1.0f); } + previousTransitionMainFragment = null; if (parentLayout != null && parentLayout.getFragmentStack().size() >= 2) { BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2); if (fragment instanceof ChatActivityInterface) { @@ -8173,6 +8197,7 @@ public AnimatorSet onCustomTransitionAnimation(final boolean isOpen, final Runna if (fragment instanceof DialogsActivity) { DialogsActivity dialogsActivity = (DialogsActivity) fragment; if (dialogsActivity.rightSlidingDialogContainer != null && dialogsActivity.rightSlidingDialogContainer.currentFragment instanceof ChatActivityInterface) { + previousTransitionMainFragment = dialogsActivity; previousTransitionFragment = (ChatActivityInterface) dialogsActivity.rightSlidingDialogContainer.currentFragment; } } @@ -8430,6 +8455,7 @@ public void onAnimationEnd(Animator animation) { avatarContainer2.invalidate(); profileTransitionInProgress = false; previousTransitionFragment = null; + previousTransitionMainFragment = null; fragmentView.invalidate(); } }); @@ -8453,6 +8479,7 @@ private void updateOnlineCount(boolean notify) { int currentTime = getConnectionsManager().getCurrentTime(); sortedUsers.clear(); if (chatInfo instanceof TLRPC.TL_chatFull || chatInfo instanceof TLRPC.TL_channelFull && chatInfo.participants_count <= 200 && chatInfo.participants != null) { + final ArrayList sortNum = new ArrayList<>(); for (int a = 0; a < chatInfo.participants.participants.size(); a++) { TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); TLRPC.User user = getMessagesController().getUser(participant.user_id); @@ -8460,22 +8487,21 @@ private void updateOnlineCount(boolean notify) { onlineCount++; } sortedUsers.add(a); + int sort = Integer.MIN_VALUE; + if (user != null) { + if (user.bot) { + sort = -110; + } else if (user.self) { + sort = currentTime + 50000; + } else if (user.status != null) { + sort = user.status.expires; + } + } + sortNum.add(sort); } try { - Collections.sort(sortedUsers, Comparator.comparingInt(hs -> { - TLRPC.User user = getMessagesController().getUser(chatInfo.participants.participants.get((int) hs).user_id); - if (user != null) { - if (user.bot) { - return -110; - } else if (user.self) { - return currentTime + 50000; - } else if (user.status != null) { - return user.status.expires; - } - } - return Integer.MIN_VALUE; - }).reversed()); + Collections.sort(sortedUsers, Comparator.comparingInt(hs -> sortNum.get((int) hs)).reversed()); } catch (Exception e) { FileLog.e(e); } @@ -8720,6 +8746,9 @@ private void updateRowsIds() { if (!hasMedia && userInfo != null && userInfo.bot_info != null) { hasMedia = userInfo.bot_info.has_preview_medias; } + if (!hasMedia && userInfo != null && userInfo.stargifts_count > 0) { + hasMedia = true; + } if (!hasMedia && chatInfo != null) { hasMedia = chatInfo.stories_pinned_available; } @@ -9262,6 +9291,8 @@ private void updateProfileData(boolean reload) { } else { newString2 = LocaleController.getString(R.string.Online); } + } else if (user.id == UserObject.VERIFY) { + newString2 = LocaleController.getString(R.string.VerifyCodesNotifications); } else if (user.id == 333000 || user.id == 777000 || user.id == 42777) { newString2 = LocaleController.getString(R.string.ServiceNotifications); } else if (MessagesController.isSupportUser(user)) { @@ -9293,10 +9324,9 @@ private void updateProfileData(boolean reload) { if (nameTextView[a] == null) { continue; } - if (a == 0 && user.id != getUserConfig().getClientUserId() && user.id / 1000 != 777 && user.id / 1000 != 333 && user.phone != null && user.phone.length() != 0 && getContactsController().contactsDict.get(user.id) == null && + if (a == 0 && user.id != getUserConfig().getClientUserId() && !MessagesController.isSupportUser(user) && user.phone != null && user.phone.length() != 0 && getContactsController().contactsDict.get(user.id) == null && (getContactsController().contactsDict.size() != 0 || !getContactsController().isLoadingContacts())) { - String phoneString = PhoneFormat.getInstance().format("+" + user.phone); - nameTextView[a].setText(phoneString); + nameTextView[a].setText(PhoneFormat.getInstance().format("+" + user.phone)); } else { nameTextView[a].setText(newString); } @@ -9330,7 +9360,7 @@ private void updateProfileData(boolean reload) { nameTextView[a].setRightDrawable2(null); nameTextViewRightDrawable2ContentDescription = null; } - if (user.emoji_status instanceof TLRPC.TL_emojiStatus || user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) { + if (!getMessagesController().premiumFeaturesBlocked() && !MessagesController.isSupportUser(user) && (user.emoji_status instanceof TLRPC.TL_emojiStatus || user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000))) { rightIconIsStatus = true; rightIconIsPremium = false; nameTextView[a].setRightDrawable(getEmojiStatusDrawable(user.emoji_status, false, false, a)); @@ -9352,7 +9382,7 @@ private void updateProfileData(boolean reload) { } else { nameTextView[a].setRightDrawable2(null); } - if (user.emoji_status instanceof TLRPC.TL_emojiStatus || user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) { + if (!getMessagesController().premiumFeaturesBlocked() && !MessagesController.isSupportUser(user) && (user.emoji_status instanceof TLRPC.TL_emojiStatus || user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000))) { rightIconIsStatus = true; rightIconIsPremium = false; nameTextView[a].setRightDrawable(getEmojiStatusDrawable(user.emoji_status, true, true, a)); @@ -9872,7 +9902,7 @@ private void createActionBarMenu(boolean animated) { otherItem.addSubItem(block_contact, R.drawable.msg_block, LocaleController.getString(R.string.Unblock)); } otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString(R.string.AddShortcut)); - } else { + } else if (getDialogId() != UserObject.VERIFY) { if (currentEncryptedChat == null) { createAutoDeleteItem(context); } @@ -9915,8 +9945,8 @@ private void createActionBarMenu(boolean animated) { otherItem.addSubItem(delete_contact, R.drawable.msg_delete, LocaleController.getString(R.string.DeleteContact)); } if (!UserObject.isDeleted(user) && !isBot && currentEncryptedChat == null && !userBlocked && userId != 333000 && userId != 777000 && userId != 42777) { - if (!user.premium && !BuildVars.IS_BILLING_UNAVAILABLE && !user.self && userInfo != null && !getMessagesController().premiumFeaturesBlocked() && !userInfo.premium_gifts.isEmpty()) { - otherItem.addSubItem(gift_premium, R.drawable.msg_gift_premium, LocaleController.getString(R.string.GiftPremium)); + if (!BuildVars.IS_BILLING_UNAVAILABLE && !user.self && !getMessagesController().premiumFeaturesBlocked()) { + otherItem.addSubItem(gift_premium, R.drawable.msg_gift_premium, LocaleController.getString(R.string.ProfileSendAGift)); } otherItem.addSubItem(start_secret_chat, R.drawable.msg_secret, LocaleController.getString(R.string.StartEncryptedChat)); otherItem.setSubItemShown(start_secret_chat, !getMessagesController().isUserPremiumBlocked(userId)); @@ -10964,12 +10994,18 @@ protected int processColor(int color) { protected void onYesClick(int type) { getNotificationCenter().removeObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); if (type == SettingsSuggestionCell.TYPE_GRACE) { - Browser.openUrl(getContext(), getMessagesController().premiumManageSubscriptionUrl); getMessagesController().removeSuggestion(0, "PREMIUM_GRACE"); - updateListAnimated(false); + updateRowsIds(); + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + } + Browser.openUrl(getContext(), getMessagesController().premiumManageSubscriptionUrl); } else { getMessagesController().removeSuggestion(0, type == SettingsSuggestionCell.TYPE_PHONE ? "VALIDATE_PHONE_NUMBER" : "VALIDATE_PASSWORD"); - updateListAnimated(false); + updateRowsIds(); + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + } } getNotificationCenter().addObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); } @@ -11005,7 +11041,7 @@ public int processColor(int color) { button.setText(LocaleController.getString(R.string.ProfileBotOpenApp), false); button.setOnClickListener(v -> { TLRPC.User bot = getMessagesController().getUser(userId); - getMessagesController().openApp(ProfileActivity.this, bot, getClassGuid(), null); + getMessagesController().openApp(ProfileActivity.this, bot, null, getClassGuid(), null); }); frameLayout.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 18, 14, 18, 14)); view = frameLayout; @@ -11419,7 +11455,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { textCell.setTextAndIcon(TextCell.applyNewSpan(LocaleController.getString(R.string.TelegramBusiness)), R.drawable.menu_shop, true); textCell.setImageLeft(23); } else if (position == premiumGiftingRow) { - textCell.setTextAndIcon(LocaleController.getString(R.string.GiftPremiumGifting), R.drawable.menu_gift, false); + textCell.setTextAndIcon(LocaleController.getString(R.string.SendAGift), R.drawable.menu_gift, false); textCell.setImageLeft(23); } textCell.valueTextView.setTextColor(applyPeerColor(getThemedColor(Theme.key_windowBackgroundWhiteValueText), false)); @@ -12795,6 +12831,10 @@ public ArrayList getThemeDescriptions() { } public void updateListAnimated(boolean updateOnlineCount) { + updateListAnimated(updateOnlineCount, false); + } + + private void updateListAnimated(boolean updateOnlineCount, boolean triedInLayout) { if (listAdapter == null) { if (updateOnlineCount) { updateOnlineCount(false); @@ -12803,6 +12843,12 @@ public void updateListAnimated(boolean updateOnlineCount) { return; } + if (!triedInLayout && listView.isInLayout()) { + if (!listView.isAttachedToWindow()) return; + listView.post(() -> updateListAnimated(updateOnlineCount, true)); + return; + } + DiffCallback diffCallback = new DiffCallback(); diffCallback.oldRowCount = rowCount; diffCallback.fillPositions(diffCallback.oldPositionToItem); @@ -12875,28 +12921,7 @@ private void onTextDetailCellImageClicked(View view) { 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()) { - if (getVisibleDialog() != null) return; - final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER); - final int reqId = BoostRepository.loadGiftOptions(null, loadedOptions -> { - progressDialog.dismiss(); - if (getVisibleDialog() != null) return; - loadedOptions = BoostRepository.filterGiftOptions(loadedOptions, 1); - loadedOptions = BoostRepository.filterGiftOptionsByBilling(loadedOptions); - ArrayList users = new ArrayList<>(); - users.add(user); - PremiumPreviewGiftToUsersBottomSheet.show(users, loadedOptions); - }); - progressDialog.setOnCancelListener(di -> { - getConnectionsManager().cancelRequest(reqId, true); - }); - progressDialog.showDelayed(500); - } else { - showDialog(new GiftPremiumBottomSheet(this, user)); - } + showDialog(new GiftSheet(getContext(), currentAccount, userId, null, null)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java deleted file mode 100644 index 171c72f3d4..0000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java +++ /dev/null @@ -1,489 +0,0 @@ -package org.telegram.ui; - -import static org.telegram.messenger.AndroidUtilities.dp; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.MessagesController; -import org.telegram.messenger.R; -import org.telegram.messenger.Utilities; -import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.BackDrawable; -import org.telegram.ui.ActionBar.BottomSheet; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Cells.HeaderCell; -import org.telegram.ui.Components.AnimatedFloat; -import org.telegram.ui.Components.CombinedDrawable; -import org.telegram.ui.Components.CubicBezierInterpolator; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.LinkSpanDrawable; -import org.telegram.ui.Components.UItem; -import org.telegram.ui.Components.UniversalAdapter; -import org.telegram.ui.Components.UniversalRecyclerView; -import org.telegram.ui.Components.ViewPagerFixed; - -import java.util.ArrayList; -import java.util.Collections; - -public class ReportAdBottomSheet extends BottomSheet { - - private final ViewPagerFixed viewPager; - private static final int PAGE_TYPE_OPTIONS = 0; - private static final int PAGE_TYPE_SUB_OPTIONS = 1; - private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - private final MessageObject messageObject; - private final TLRPC.Chat chat; - private Listener listener; - - interface Listener { - void onReported(); - void onHidden(); - void onPremiumRequired(); - } - - public ReportAdBottomSheet(Context context, Theme.ResourcesProvider resourcesProvider, MessageObject messageObject, TLRPC.Chat chat) { - super(context, true, resourcesProvider); - this.messageObject = messageObject; - this.chat = chat; - backgroundPaint.setColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); - containerView = new ContainerView(context); - viewPager = new ViewPagerFixed(context) { - @Override - protected void onTabAnimationUpdate(boolean manual) { - super.onTabAnimationUpdate(manual); - containerView.invalidate(); - } - - @Override - protected boolean canScrollForward(MotionEvent e) { - return false; - } - - }; - viewPager.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); - containerView.addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); - viewPager.setAdapter(new ViewPagerFixed.Adapter() { - @Override - public int getItemCount() { - return 5; - } - - @Override - public View createView(int viewType) { - return new Page(context); - } - - @Override - public int getItemViewType(int position) { - if (position == 0) { - return PAGE_TYPE_OPTIONS; - } else { - return PAGE_TYPE_SUB_OPTIONS; - } - } - - @Override - public void bindView(View view, int position, int viewType) { - ((Page) view).bind(viewType); - } - - }); - - if (messageObject == null) { - setReportChooseOption(null); - } - } - - public ReportAdBottomSheet setReportChooseOption(TLRPC.TL_channels_sponsoredMessageReportResultChooseOption chooseOption) { - View[] viewPages = viewPager.getViewPages(); - if (viewPages[0] instanceof Page) { - ((Page) viewPages[0]).bind(PAGE_TYPE_OPTIONS); - containerView.post(() -> ((Page) viewPages[0]).setOption(chooseOption)); - } - if (viewPages[1] instanceof Page) { - ((Page) viewPages[1]).bind(PAGE_TYPE_SUB_OPTIONS); - } - return this; - } - - public ReportAdBottomSheet setListener(Listener listener) { - this.listener = listener; - return this; - } - - @Override - public void onBackPressed() { - if (viewPager.getCurrentPosition() > 0) { - viewPager.scrollToPosition(viewPager.getCurrentPosition() - 1); - return; - } - super.onBackPressed(); - } - - @Override - protected boolean canDismissWithSwipe() { - View currentView = viewPager.getCurrentView(); - if (currentView instanceof Page) { - return ((Page) currentView).atTop(); - } - return true; - } - - private void submitOption(CharSequence optionText, byte[] option) { - TLRPC.TL_channels_reportSponsoredMessage req = new TLRPC.TL_channels_reportSponsoredMessage(); - req.channel = MessagesController.getInputChannel(chat); - req.random_id = messageObject.sponsoredId; - req.option = option; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - AndroidUtilities.runOnUIThread(() -> { - if (response != null) { - if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) { - TLRPC.TL_channels_sponsoredMessageReportResultChooseOption result = (TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) response; - int nextPosition = viewPager.currentPosition + 1; - viewPager.scrollToPosition(nextPosition); - Page nextPage = (Page) viewPager.getViewPages()[1]; - if (nextPage != null) { - nextPage.setOption(result); - if (optionText != null) { - nextPage.setHeaderText(optionText); - } - } - } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultAdsHidden) { - MessagesController.getInstance(currentAccount).disableAds(false); - if (listener != null) { - listener.onHidden(); - dismiss(); - } - } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultReported) { - if (listener != null) { - listener.onReported(); - dismiss(); - } - } - } else if (error != null) { - if ("PREMIUM_ACCOUNT_REQUIRED".equals(error.text)) { - if (listener != null) { - listener.onPremiumRequired(); - } - } else if ("AD_EXPIRED".equals(error.text)) { - if (listener != null) { - listener.onReported(); - } - } - dismiss(); - } - }); - }); - } - - private class ContainerView extends FrameLayout { - private final AnimatedFloat isActionBar = new AnimatedFloat(this, 250, CubicBezierInterpolator.EASE_OUT_QUINT); - private float top; - private final Path path = new Path(); - private Boolean statusBarOpen; - - public ContainerView(Context context) { - super(context); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - View[] views = viewPager.getViewPages(); - top = 0; - for (View view : views) { - if (view == null) { - continue; - } - final Page page = (Page) view; - float t = Utilities.clamp(1f - Math.abs(page.getTranslationX() / (float) page.getMeasuredWidth()), 1, 0); - top += page.top() * t; - if (page.getVisibility() == View.VISIBLE) { - page.updateTops(); - } - } - float actionBarT = isActionBar.set(top <= AndroidUtilities.statusBarHeight ? 1f : 0f); - float statusBarHeight = AndroidUtilities.statusBarHeight * actionBarT; - top = Math.max(AndroidUtilities.statusBarHeight, top) - AndroidUtilities.statusBarHeight * actionBarT; - AndroidUtilities.rectTmp.set(backgroundPaddingLeft, top, getWidth() - backgroundPaddingLeft, getHeight() + dp(8)); - final float r = AndroidUtilities.lerp(dp(14), 0, actionBarT); - canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, backgroundPaint); - canvas.save(); - path.rewind(); - path.addRoundRect(AndroidUtilities.rectTmp, r, r, Path.Direction.CW); - canvas.clipPath(path); - super.dispatchDraw(canvas); - canvas.restore(); - updateLightStatusBar(statusBarHeight > AndroidUtilities.statusBarHeight / 2f); - } - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - return super.drawChild(canvas, child, drawingTime); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < top) { - dismiss(); - return true; - } - return super.dispatchTouchEvent(event); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); - } - - private void updateLightStatusBar(boolean open) { - if (statusBarOpen != null && statusBarOpen == open) { - return; - } - boolean openBgLight = AndroidUtilities.computePerceivedBrightness(getThemedColor(Theme.key_dialogBackground)) > .721f; - boolean closedBgLight = AndroidUtilities.computePerceivedBrightness(Theme.blendOver(getThemedColor(Theme.key_actionBarDefault), 0x33000000)) > .721f; - boolean isLight = (statusBarOpen = open) ? openBgLight : closedBgLight; - AndroidUtilities.setLightStatusBar(getWindow(), isLight); - } - } - - private class Page extends FrameLayout { - int pageType; - TLRPC.TL_channels_sponsoredMessageReportResultChooseOption option; - - private final FrameLayout contentView; - private final UniversalRecyclerView listView; - private final BigHeaderCell headerView; - - public Page(Context context) { - super(context); - - contentView = new FrameLayout(context); - contentView.setPadding(0, AndroidUtilities.statusBarHeight, 0, 0); - contentView.setClipToPadding(true); - addView(contentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); - - headerView = new BigHeaderCell(context, resourcesProvider); - headerView.setOnBackClickListener(() -> { - if (pageType == PAGE_TYPE_OPTIONS) { - dismiss(); - } else { - onBackPressed(); - } - }); - headerView.setText(LocaleController.getString(R.string.ReportAd)); - headerView.backDrawable.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); - headerView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); - addView(headerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL)); - - listView = new UniversalRecyclerView(context, currentAccount, 0, this::fillItems, this::onClick, null, resourcesProvider); - listView.setClipToPadding(false); - listView.layoutManager.setReverseLayout(true); - listView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - contentView.invalidate(); - containerView.invalidate(); - } - }); - contentView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - } - - public float top() { - float top = contentView.getPaddingTop(); - for (int i = 0; i < listView.getChildCount(); ++i) { - View child = listView.getChildAt(i); - int position = listView.layoutManager.getPosition(child); - if (position < 0 || position >= listView.adapter.getItemCount()) - continue; - UItem uItem = listView.adapter.getItem(position); - if (uItem != null && uItem.viewType == UniversalAdapter.VIEW_TYPE_SPACE) { - top = contentView.getPaddingTop() + child.getY(); - } - } - return top; - } - - public void updateTops() { - float top = -headerView.getHeight(); - for (int i = 0; i < listView.getChildCount(); ++i) { - View child = listView.getChildAt(i); - int position = listView.layoutManager.getPosition(child); - UItem uItem = listView.adapter.getItem(position); - if (uItem.viewType == UniversalAdapter.VIEW_TYPE_SPACE) { - top = contentView.getPaddingTop() + child.getY(); - break; - } - } - headerView.setTranslationY(Math.max(AndroidUtilities.statusBarHeight, top)); - } - - public void bind(int pageType) { - this.pageType = pageType; - headerView.setCloseImageVisible(pageType != PAGE_TYPE_OPTIONS); - if (listView != null) { - listView.adapter.update(true); - } - } - - public void setOption(TLRPC.TL_channels_sponsoredMessageReportResultChooseOption option) { - this.option = option; - listView.adapter.update(false); - } - - public void setHeaderText(CharSequence headerText) { - headerView.setText(headerText); - headerView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(120), MeasureSpec.AT_MOST)); - if (listView != null) { - listView.adapter.update(true); - } - } - - public void fillItems(ArrayList items, UniversalAdapter adapter) { - int height = 0; - - if (headerView.getMeasuredHeight() <= 0) { - headerView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(120), MeasureSpec.AT_MOST)); - } - UItem space = UItem.asSpace(headerView.getMeasuredHeight()); - space.id = -1; - space.transparent = true; - items.add(space); - height += headerView.getMeasuredHeight() / AndroidUtilities.density; - - if (option != null) { - HeaderCell headerCell = new HeaderCell(getContext(), Theme.key_windowBackgroundWhiteBlueHeader, 21, 0, 0, false, resourcesProvider); - headerCell.setText(option.title); - headerCell.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); - UItem headerItem = UItem.asCustom(headerCell); - headerItem.id = -2; - items.add(headerItem); - height += 40; - - 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.iconResId = R.drawable.msg_arrowright; - buttonItem.id = i; - items.add(buttonItem); - height += 50; - } - items.get(items.size() - 1).hideDivider = true; - - if (pageType == PAGE_TYPE_OPTIONS) { - FrameLayout frameLayout = new FrameLayout(getContext()); - Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); - Drawable background = new ColorDrawable(getThemedColor(Theme.key_windowBackgroundGray)); - CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); - combinedDrawable.setFullsize(true); - frameLayout.setBackground(combinedDrawable); - LinkSpanDrawable.LinksTextView textView = new LinkSpanDrawable.LinksTextView(getContext()); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView.setText(AndroidUtilities.replaceLinks(LocaleController.getString(R.string.ReportAdLearnMore), resourcesProvider)); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3, resourcesProvider)); - textView.setGravity(Gravity.CENTER); - frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 16, 16, 16, 16)); - UItem bottomItem = UItem.asCustom(frameLayout); - bottomItem.id = -3; - items.add(bottomItem); - height += 46; - } - } - - if (listView != null) { - if (containerView.getMeasuredHeight() - AndroidUtilities.statusBarHeight < AndroidUtilities.dp(height)) { - listView.layoutManager.setReverseLayout(false); - } else { - Collections.reverse(items); - listView.layoutManager.setReverseLayout(true); - } - } - } - - private void onClick(UItem item, View view, int position, float x, float y) { - if (item.viewType == UniversalAdapter.VIEW_TYPE_RIGHT_ICON_TEXT) { - if (option != null) { - TLRPC.TL_sponsoredMessageReportOption clickedOption = option.options.get(item.id); - if (clickedOption != null) { - submitOption(clickedOption.text, clickedOption.option); - } - } else { - submitOption(item.text, null); - } - } - } - - public boolean atTop() { - return !listView.canScrollVertically(-1); - } - - private class BigHeaderCell extends FrameLayout { - private final ImageView btnBack; - private final TextView textView; - public BackDrawable backDrawable; - private Runnable onBackClickListener; - - public BigHeaderCell(Context context, Theme.ResourcesProvider resourcesProvider) { - super(context); - textView = new TextView(context); - textView.setTypeface(AndroidUtilities.bold()); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); - addView(textView); - - btnBack = new ImageView(context); - btnBack.setImageDrawable(backDrawable = new BackDrawable(false)); - backDrawable.setColor(0xffffffff); - addView(btnBack, LayoutHelper.createFrame(24, 24, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 16, 16, 16, 0)); - btnBack.setOnClickListener(e -> { - if (onBackClickListener != null) { - onBackClickListener.run(); - } - }); - - setCloseImageVisible(true); - setMinimumHeight(dp(56)); - } - - public void setText(CharSequence text) { - textView.setText(text); - } - - public void setCloseImageVisible(boolean visible) { - btnBack.setVisibility(visible ? View.VISIBLE : View.GONE); - textView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, LocaleController.isRTL || !visible ? 22 : 53, 14, LocaleController.isRTL && visible ? 53 : 22, 12)); - } - - public void setOnBackClickListener(Runnable onCloseClickListener) { - this.onBackClickListener = onCloseClickListener; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure( - MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), - heightMeasureSpec - ); - } - } - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ReportBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ReportBottomSheet.java new file mode 100644 index 0000000000..872a9c6d5d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ReportBottomSheet.java @@ -0,0 +1,1035 @@ +package org.telegram.ui; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.DialogObject; +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.messenger.browser.Browser; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.BackDrawable; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.EditTextCell; +import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; +import org.telegram.ui.Components.UItem; +import org.telegram.ui.Components.UniversalAdapter; +import org.telegram.ui.Components.UniversalRecyclerView; +import org.telegram.ui.Components.ViewPagerFixed; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +public class ReportBottomSheet extends BottomSheet { + + private final ViewPagerFixed viewPager; + private static final int PAGE_TYPE_OPTIONS = 0; + private static final int PAGE_TYPE_SUB_OPTIONS = 1; + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final boolean sponsored; + private final boolean stories; + private final ArrayList messageIds; + private final byte[] sponsoredId; + private final long dialogId; + private Listener listener; + + interface Listener { + default void onReported() {}; + default void onHidden() {}; + default void onPremiumRequired() {}; + } + + public ReportBottomSheet( + Context context, + Theme.ResourcesProvider resourcesProvider, + boolean stories, + long dialogId, + int messageId + ) { + this(context, resourcesProvider, stories, dialogId, new ArrayList<>(Arrays.asList(messageId))); + } + + public ReportBottomSheet( + Context context, + Theme.ResourcesProvider resourcesProvider, + boolean stories, + long dialogId, + ArrayList messageIds + ) { + this(false, context, resourcesProvider, dialogId, stories, messageIds, null); + } + + public ReportBottomSheet( + Context context, + Theme.ResourcesProvider resourcesProvider, + long dialogId, + byte[] sponsoredId + ) { + this(true, context, resourcesProvider, dialogId, false, null, sponsoredId); + } + + public ReportBottomSheet( + final boolean sponsored, + Context context, + Theme.ResourcesProvider resourcesProvider, + long dialogId, + boolean stories, + ArrayList messageIds, + byte[] sponsoredId + ) { + super(context, true, resourcesProvider); + this.sponsored = sponsored; + this.messageIds = messageIds; + this.stories = stories; + this.sponsoredId = sponsoredId; + this.dialogId = dialogId; + backgroundPaint.setColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + fixNavigationBar(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + smoothKeyboardAnimationEnabled = true; + smoothKeyboardByBottom = true; + containerView = new ContainerView(context); + viewPager = new ViewPagerFixed(context) { + @Override + protected void onTabAnimationUpdate(boolean manual) { + super.onTabAnimationUpdate(manual); + containerView.invalidate(); + } + + @Override + protected boolean canScrollForward(MotionEvent e) { + return false; + } + + @Override + public void onStartTracking() { + if (getCurrentView() instanceof Page) { + Page page = (Page) getCurrentView(); + if (page.editTextCell != null) { + AndroidUtilities.hideKeyboard(page.editTextCell); + } + } + } + }; + viewPager.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + containerView.addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); + viewPager.setAdapter(new ViewPagerFixed.Adapter() { + @Override + public int getItemCount() { + return 5; + } + + @Override + public View createView(int viewType) { + return new Page(context); + } + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return PAGE_TYPE_OPTIONS; + } else { + return PAGE_TYPE_SUB_OPTIONS; + } + } + + @Override + public void bindView(View view, int position, int viewType) { + ((Page) view).bind(viewType); + } + + }); + + if (messageIds == null && sponsoredId == null) { + if (sponsored) { + setReportChooseOption((TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) null); + } else { + setReportChooseOption((TLRPC.TL_reportResultChooseOption) null); + } + } + } + + public ReportBottomSheet setReportChooseOption(TLRPC.TL_channels_sponsoredMessageReportResultChooseOption chooseOption) { + View[] viewPages = viewPager.getViewPages(); + if (viewPages[0] instanceof Page) { + ((Page) viewPages[0]).bind(PAGE_TYPE_OPTIONS); + containerView.post(() -> ((Page) viewPages[0]).setOption(chooseOption)); + } + if (viewPages[1] instanceof Page) { + ((Page) viewPages[1]).bind(PAGE_TYPE_SUB_OPTIONS); + } + return this; + } + + public ReportBottomSheet setReportChooseOption(TLRPC.TL_reportResultChooseOption chooseOption) { + View[] viewPages = viewPager.getViewPages(); + if (viewPages[0] instanceof Page) { + ((Page) viewPages[0]).bind(PAGE_TYPE_OPTIONS); + containerView.post(() -> ((Page) viewPages[0]).setOption(chooseOption)); + } + if (viewPages[1] instanceof Page) { + ((Page) viewPages[1]).bind(PAGE_TYPE_SUB_OPTIONS); + } + return this; + } + + public ReportBottomSheet setReportChooseOption(TLRPC.TL_reportResultAddComment chooseOption) { + View[] viewPages = viewPager.getViewPages(); + if (viewPages[0] instanceof Page) { + ((Page) viewPages[0]).bind(PAGE_TYPE_OPTIONS); + containerView.post(() -> ((Page) viewPages[0]).setOption(chooseOption)); + } + if (viewPages[1] instanceof Page) { + ((Page) viewPages[1]).bind(PAGE_TYPE_SUB_OPTIONS); + } + return this; + } + + public ReportBottomSheet setListener(Listener listener) { + this.listener = listener; + return this; + } + + @Override + public void onBackPressed() { + if (viewPager.getCurrentView() instanceof Page) { + Page page = (Page) viewPager.getCurrentView(); + if (page.editTextCell != null) { + AndroidUtilities.hideKeyboard(page.editTextCell); + } + } + if (viewPager.getCurrentPosition() > 0) { + viewPager.scrollToPosition(viewPager.getCurrentPosition() - 1); + return; + } + super.onBackPressed(); + } + + @Override + protected boolean canDismissWithSwipe() { + View currentView = viewPager.getCurrentView(); + if (currentView instanceof Page) { + return ((Page) currentView).atTop(); + } + return true; + } + + private void submitOption(final CharSequence optionText, final byte[] option, final String comment) { + TLObject request; + if (sponsored) { + TLRPC.TL_channels_reportSponsoredMessage req = new TLRPC.TL_channels_reportSponsoredMessage(); + req.channel = MessagesController.getInstance(currentAccount).getInputChannel(-dialogId); + req.random_id = sponsoredId; + req.option = option; + request = req; + } else if (stories) { + TL_stories.TL_stories_report req = new TL_stories.TL_stories_report(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + if (messageIds != null) { + req.id.addAll(messageIds); + } + req.message = comment == null ? "" : comment; + req.option = option; + request = req; + } else { + TLRPC.TL_messages_report req = new TLRPC.TL_messages_report(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + if (messageIds != null) { + req.id.addAll(messageIds); + } + req.message = comment == null ? "" : comment; + req.option = option; + request = req; + } + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + if (viewPager.getCurrentView() instanceof Page) { + Page page = (Page) viewPager.getCurrentView(); + if (page.button != null) { + page.button.setLoading(false); + } + } + if (response != null) { + if ( + response instanceof TLRPC.TL_channels_sponsoredMessageReportResultChooseOption || + response instanceof TLRPC.TL_reportResultChooseOption || + response instanceof TLRPC.TL_reportResultAddComment + ) { + int nextPosition = viewPager.currentPosition + 1; + viewPager.scrollToPosition(nextPosition); + Page nextPage = (Page) viewPager.getViewPages()[1]; + if (nextPage != null) { + if (response instanceof TLRPC.TL_reportResultChooseOption) { + nextPage.setOption((TLRPC.TL_reportResultChooseOption) response); + } else if (response instanceof TLRPC.TL_reportResultAddComment) { + nextPage.setOption((TLRPC.TL_reportResultAddComment) response); + } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) { + nextPage.setOption((TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) response); + } + if (optionText != null) { + nextPage.setHeaderText(optionText); + } + } + } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultAdsHidden) { + MessagesController.getInstance(currentAccount).disableAds(false); + if (listener != null) { + listener.onHidden(); + dismiss(); + } + } else if ( + response instanceof TLRPC.TL_channels_sponsoredMessageReportResultReported || + response instanceof TLRPC.TL_reportResultReported + ) { + if (listener != null) { + listener.onReported(); + dismiss(); + } + } + } else if (error != null) { + if (!sponsored && "MESSAGE_ID_REQUIRED".equals(error.text)) { + ChatActivity.openReportChat(dialogId, optionText.toString(), option); + } else if ("PREMIUM_ACCOUNT_REQUIRED".equals(error.text)) { + if (listener != null) { + listener.onPremiumRequired(); + } + } else if ("AD_EXPIRED".equals(error.text)) { + if (listener != null) { + listener.onReported(); + } + } + dismiss(); + } + }); + }); + } + + private class ContainerView extends FrameLayout { + private final AnimatedFloat isActionBar = new AnimatedFloat(this, 250, CubicBezierInterpolator.EASE_OUT_QUINT); + private float top; + private final Path path = new Path(); + private Boolean statusBarOpen; + + public ContainerView(Context context) { + super(context); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + View[] views = viewPager.getViewPages(); + top = 0; + for (View view : views) { + if (view == null) { + continue; + } + final Page page = (Page) view; + float t = Utilities.clamp(1f - Math.abs(page.getTranslationX() / (float) page.getMeasuredWidth()), 1, 0); + top += page.top() * t; + if (page.getVisibility() == View.VISIBLE) { + page.updateTops(); + } + } + float actionBarT = isActionBar.set(top <= AndroidUtilities.statusBarHeight ? 1f : 0f); + float statusBarHeight = AndroidUtilities.statusBarHeight * actionBarT; + top = Math.max(AndroidUtilities.statusBarHeight, top) - AndroidUtilities.statusBarHeight * actionBarT; + AndroidUtilities.rectTmp.set(backgroundPaddingLeft, top, getWidth() - backgroundPaddingLeft, getHeight() + dp(8)); + final float r = AndroidUtilities.lerp(dp(14), 0, actionBarT); + canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, backgroundPaint); + canvas.save(); + path.rewind(); + path.addRoundRect(AndroidUtilities.rectTmp, r, r, Path.Direction.CW); + canvas.clipPath(path); + super.dispatchDraw(canvas); + canvas.restore(); + updateLightStatusBar(statusBarHeight > AndroidUtilities.statusBarHeight / 2f); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + return super.drawChild(canvas, child, drawingTime); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < top) { + dismiss(); + return true; + } + return super.dispatchTouchEvent(event); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); + } + + private void updateLightStatusBar(boolean open) { + if (statusBarOpen != null && statusBarOpen == open) { + return; + } + boolean openBgLight = AndroidUtilities.computePerceivedBrightness(getThemedColor(Theme.key_dialogBackground)) > .721f; + boolean closedBgLight = AndroidUtilities.computePerceivedBrightness(Theme.blendOver(getThemedColor(Theme.key_actionBarDefault), 0x33000000)) > .721f; + boolean isLight = (statusBarOpen = open) ? openBgLight : closedBgLight; + AndroidUtilities.setLightStatusBar(getWindow(), isLight); + } + } + + private class Page extends FrameLayout { + int pageType; + + TLRPC.TL_channels_sponsoredMessageReportResultChooseOption sponsoredOption; + TLRPC.TL_reportResultChooseOption option; + TLRPC.TL_reportResultAddComment commentOption; + + private final FrameLayout contentView; + private final UniversalRecyclerView listView; + private final BigHeaderCell headerView; + + public Page(Context context) { + super(context); + + contentView = new FrameLayout(context); + contentView.setPadding(0, AndroidUtilities.statusBarHeight, 0, 0); + contentView.setClipToPadding(true); + addView(contentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); + + headerView = new BigHeaderCell(context, resourcesProvider); + headerView.setOnBackClickListener(() -> { + if (pageType == PAGE_TYPE_OPTIONS) { + dismiss(); + } else { + onBackPressed(); + } + }); + if (sponsored) { + headerView.setText(LocaleController.getString(R.string.ReportAd)); + } else if (stories) { + headerView.setText(LocaleController.getString(R.string.ReportStory)); + } else { + headerView.setText(LocaleController.getString(R.string.Report2)); + } + headerView.backDrawable.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + headerView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + addView(headerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL)); + + listView = new UniversalRecyclerView(context, currentAccount, 0, true, this::fillItems, this::onClick, null, resourcesProvider); + listView.setClipToPadding(false); + listView.layoutManager.setReverseLayout(true); + listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + contentView.invalidate(); + containerView.invalidate(); + } + }); + contentView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } + + public float top() { + float top = contentView.getPaddingTop(); + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + int position = listView.layoutManager.getPosition(child); + if (position < 0 || position >= listView.adapter.getItemCount()) + continue; + UItem uItem = listView.adapter.getItem(position); + if (uItem != null && uItem.viewType == UniversalAdapter.VIEW_TYPE_SPACE) { + top = contentView.getPaddingTop() + child.getY(); + } + } + return top; + } + + public void updateTops() { + float top = -headerView.getHeight(); + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + int position = listView.layoutManager.getPosition(child); + UItem uItem = listView.adapter.getItem(position); + if (uItem.viewType == UniversalAdapter.VIEW_TYPE_SPACE) { + top = contentView.getPaddingTop() + child.getY(); + break; + } + } + headerView.setTranslationY(Math.max(AndroidUtilities.statusBarHeight, top)); + } + + public void bind(int pageType) { + this.pageType = pageType; + headerView.setCloseImageVisible(pageType != PAGE_TYPE_OPTIONS); + if (listView != null) { + listView.adapter.update(true); + } + } + + public void setOption(TLRPC.TL_channels_sponsoredMessageReportResultChooseOption option) { + this.sponsoredOption = option; + this.option = null; + this.commentOption = null; + listView.adapter.update(false); + } + + public void setOption(TLRPC.TL_reportResultChooseOption option) { + this.sponsoredOption = null; + this.option = option; + this.commentOption = null; + listView.adapter.update(false); + } + + public void setOption(TLRPC.TL_reportResultAddComment option) { + this.sponsoredOption = null; + this.option = null; + this.commentOption = option; + listView.adapter.update(false); + if (editTextCell != null) { + AndroidUtilities.runOnUIThread(() -> { + AndroidUtilities.showKeyboard(editTextCell.editText); + }, 120); + } + } + + public void setHeaderText(CharSequence headerText) { + headerView.setText(headerText); + headerView.getText(); + headerView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(120), MeasureSpec.AT_MOST)); + if (listView != null) { + listView.adapter.update(true); + } + } + + private EditTextCell editTextCell; + private FrameLayout buttonContainer; + private ButtonWithCounterView button; + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + int height = 0; + + if (headerView.getMeasuredHeight() <= 0) { + headerView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(120), MeasureSpec.AT_MOST)); + } + UItem space = UItem.asSpace(headerView.getMeasuredHeight()); + space.id = -1; + space.transparent = true; + items.add(space); + height += headerView.getMeasuredHeight() / AndroidUtilities.density; + + if (sponsoredOption != null || option != null || commentOption != null) { + if (sponsoredOption != null || option != null) { + HeaderCell headerCell = new HeaderCell(getContext(), Theme.key_windowBackgroundWhiteBlueHeader, 21, 0, 0, false, resourcesProvider); + if (sponsoredOption != null) { + headerCell.setText(sponsoredOption.title); + } else if (option != null) { + headerCell.setText(option.title); + } + headerCell.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + UItem headerItem = UItem.asCustom(headerCell); + headerItem.id = -2; + items.add(headerItem); + height += 40; + } + + if (sponsoredOption != null) { + for (int i = 0; i < sponsoredOption.options.size(); i++) { + UItem buttonItem = new UItem(UniversalAdapter.VIEW_TYPE_RIGHT_ICON_TEXT, false); + buttonItem.text = sponsoredOption.options.get(i).text; + buttonItem.iconResId = R.drawable.msg_arrowright; + buttonItem.id = i; + items.add(buttonItem); + height += 50; + } + } else if (option != null) { + 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.iconResId = R.drawable.msg_arrowright; + buttonItem.id = i; + items.add(buttonItem); + height += 50; + } + } else if (commentOption != null) { + if (editTextCell == null) { + editTextCell = new EditTextCell(getContext(), "", true, false, 1024, resourcesProvider) { + @Override + protected void onTextChanged(CharSequence newText) { + super.onTextChanged(newText); + if (button != null) { + button.setEnabled(commentOption.optional || !TextUtils.isEmpty(editTextCell.getText())); + } + } + }; + editTextCell.setShowLimitWhenNear(100); + } + editTextCell.editText.setHint(LocaleController.getString(commentOption.optional ? R.string.Report2CommentOptional : R.string.Report2Comment)); + UItem item = UItem.asCustom(editTextCell); + item.id = -3; + items.add(item); + height += 40; + + if (messageIds != null && !messageIds.isEmpty()) { + items.add(UItem.asShadow(LocaleController.getString(messageIds.size() > 1 ? R.string.Report2CommentInfoMany : R.string.Report2CommentInfo))); + } else if (DialogObject.isUserDialog(dialogId)) { + items.add(UItem.asShadow(LocaleController.getString(R.string.Report2CommentInfoUser))); + } else if (ChatObject.isChannelAndNotMegaGroup(MessagesController.getInstance(currentAccount).getChat(-dialogId))) { + items.add(UItem.asShadow(LocaleController.getString(R.string.Report2CommentInfoChannel))); + } else { + items.add(UItem.asShadow(LocaleController.getString(R.string.Report2CommentInfoGroup))); + } + + if (buttonContainer == null) { + button = new ButtonWithCounterView(getContext(), resourcesProvider); + button.setText(LocaleController.getString(R.string.Report2Send), false); + + buttonContainer = new FrameLayout(getContext()); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + buttonContainer.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 12, 12, 12, 12)); + + View buttonShadow = new View(getContext()); + buttonShadow.setBackgroundColor(Theme.getColor(Theme.key_divider, resourcesProvider)); + buttonContainer.addView(buttonShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1f / AndroidUtilities.density, Gravity.TOP)); + } + button.setEnabled(commentOption.optional || !TextUtils.isEmpty(editTextCell.getText())); + button.setOnClickListener(v -> { + if (!button.isEnabled() || button.isLoading()) return; + button.setLoading(true); + submitOption(headerView.getText(), commentOption.option, editTextCell.getText().toString()); + }); + + UItem buttonItem = UItem.asCustom(buttonContainer); + buttonItem.id = -4; + items.add(buttonItem); + height += 12 + 48 + 12; + } + items.get(items.size() - 1).hideDivider = true; + + if (sponsored && pageType == PAGE_TYPE_OPTIONS) { + FrameLayout frameLayout = new FrameLayout(getContext()); + Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); + Drawable background = new ColorDrawable(getThemedColor(Theme.key_windowBackgroundGray)); + CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); + combinedDrawable.setFullsize(true); + frameLayout.setBackground(combinedDrawable); + LinkSpanDrawable.LinksTextView textView = new LinkSpanDrawable.LinksTextView(getContext()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setText(AndroidUtilities.replaceLinks(LocaleController.getString(R.string.ReportAdLearnMore), resourcesProvider)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3, resourcesProvider)); + textView.setGravity(Gravity.CENTER); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 16, 16, 16, 16)); + UItem bottomItem = UItem.asCustom(frameLayout); + bottomItem.id = -3; + items.add(bottomItem); + height += 46; + } + } + + if (listView != null) { + if (containerView.getMeasuredHeight() - AndroidUtilities.statusBarHeight < AndroidUtilities.dp(height)) { + listView.layoutManager.setReverseLayout(false); + } else { + Collections.reverse(items); + listView.layoutManager.setReverseLayout(true); + } + } + } + + private void onClick(UItem item, View view, int position, float x, float y) { + if (item.viewType == UniversalAdapter.VIEW_TYPE_RIGHT_ICON_TEXT) { + if (sponsoredOption != null) { + TLRPC.TL_sponsoredMessageReportOption clickedOption = sponsoredOption.options.get(item.id); + if (clickedOption != null) { + submitOption(clickedOption.text, clickedOption.option, null); + } + } else if (option != null) { + TLRPC.TL_messageReportOption clickedOption = option.options.get(item.id); + if (clickedOption != null) { + submitOption(clickedOption.text, clickedOption.option, null); + } + } else if (commentOption != null) { + if (commentOption.option != null) { + submitOption(null, commentOption.option, null); + } + } else { + submitOption(item.text, null, null); + } + } + } + + public boolean atTop() { + return !listView.canScrollVertically(-1); + } + + private class BigHeaderCell extends FrameLayout { + private final ImageView btnBack; + private final TextView textView; + public BackDrawable backDrawable; + private Runnable onBackClickListener; + + public BigHeaderCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + textView = new TextView(context); + textView.setTypeface(AndroidUtilities.bold()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + addView(textView); + + btnBack = new ImageView(context); + btnBack.setImageDrawable(backDrawable = new BackDrawable(false)); + backDrawable.setColor(0xffffffff); + addView(btnBack, LayoutHelper.createFrame(24, 24, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 16, 16, 16, 0)); + btnBack.setOnClickListener(e -> { + if (onBackClickListener != null) { + onBackClickListener.run(); + } + }); + + setCloseImageVisible(true); + setMinimumHeight(dp(56)); + } + + public void setText(CharSequence text) { + textView.setText(text); + } + + public CharSequence getText() { + return textView.getText(); + } + + public void setCloseImageVisible(boolean visible) { + btnBack.setVisibility(visible ? View.VISIBLE : View.GONE); + textView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, LocaleController.isRTL || !visible ? 22 : 53, 14, LocaleController.isRTL && visible ? 53 : 22, 12)); + } + + public void setOnBackClickListener(Runnable onCloseClickListener) { + this.onBackClickListener = onCloseClickListener; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + heightMeasureSpec + ); + } + } + } + + public static void openChat( + int currentAccount, + Context context, + long dialogId + ) { + open(currentAccount, context, dialogId, false, new ArrayList<>(), null, null, new byte[]{}, null); + } + + public static void openChat( + ChatActivity fragment + ) { + if (fragment == null) return; + final int currentAccount = fragment.getCurrentAccount(); + final Context context = fragment.getContext(); + final long dialogId = fragment.getDialogId(); + if (context == null) return; + + open(currentAccount, context, dialogId, false, new ArrayList<>(), null, null, new byte[]{}, null); + } + + public static void openChat( + BaseFragment fragment, + long dialogId + ) { + if (fragment == null) return; + final int currentAccount = fragment.getCurrentAccount(); + final Context context = fragment.getContext(); + if (context == null) return; + + open(currentAccount, context, dialogId, false, new ArrayList<>(), null, null, new byte[]{}, null); + } + + public static void openMessage( + BaseFragment fragment, + MessageObject message + ) { + if (fragment == null) return; + final int currentAccount = fragment.getCurrentAccount(); + final Context context = fragment.getContext(); + if (context == null) return; + + final ArrayList messageIds = new ArrayList<>(Collections.singleton(message.getId())); + open(currentAccount, context, message.getDialogId(), false, messageIds, BulletinFactory.of(fragment), fragment == null ? null : fragment.getResourceProvider(), new byte[]{}, null); + } + + public static void openMessages( + ChatActivity fragment, + ArrayList ids + ) { + if (fragment == null) return; + final int currentAccount = fragment.getCurrentAccount(); + final Context context = fragment.getContext(); + final long dialogId = fragment.getDialogId(); + if (context == null) return; + + open(currentAccount, context, dialogId, false, ids, BulletinFactory.of(fragment), fragment == null ? null : fragment.getResourceProvider(), new byte[]{}, null); + } + + public static void continueReport( + ChatActivity fragment, + byte[] option, + ArrayList ids, + Utilities.Callback whenDone + ) { + if (fragment == null) return; + final int currentAccount = fragment.getCurrentAccount(); + final Context context = fragment.getContext(); + final long dialogId = fragment.getDialogId(); + if (context == null) return; + + open(currentAccount, context, dialogId, false, ids, BulletinFactory.of(fragment), fragment == null ? null : fragment.getResourceProvider(), option, whenDone); + } + + public static void openStory( + int currentAccount, + Context context, + TL_stories.StoryItem storyItem, + BulletinFactory bulletinFactory, + Theme.ResourcesProvider resourceProvider, + Utilities.Callback whenDone + ) { + final ArrayList storyIds = new ArrayList<>(Collections.singleton(storyItem.id)); + open(currentAccount, context, storyItem.dialogId, true, storyIds, bulletinFactory, resourceProvider, new byte[]{}, whenDone); + } + + public static void open( + int currentAccount, + Context context, + long dialogId, + boolean stories, + ArrayList messageIds, + BulletinFactory bulletinFactory, + Theme.ResourcesProvider resourceProvider, + final byte[] option, + Utilities.Callback whenDone + ) { + if (context == null || messageIds == null) return; + final boolean[] done = new boolean[] { false }; + final TLObject request; + if (stories) { + TL_stories.TL_stories_report req = new TL_stories.TL_stories_report(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.id.addAll(messageIds); + req.option = option; + req.message = ""; + request = req; + } else { + TLRPC.TL_messages_report req = new TLRPC.TL_messages_report(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.id.addAll(messageIds); + req.option = option; + req.message = ""; + request = req; + } + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + if (response != null) { + if (response instanceof TLRPC.TL_reportResultChooseOption || response instanceof TLRPC.TL_reportResultAddComment) { + AndroidUtilities.runOnUIThread(() -> { + final ReportBottomSheet sheet = new ReportBottomSheet(context, resourceProvider, stories, dialogId, messageIds); + if (response instanceof TLRPC.TL_reportResultChooseOption) { + sheet.setReportChooseOption((TLRPC.TL_reportResultChooseOption) response); + } else if (response instanceof TLRPC.TL_reportResultAddComment) { + sheet.setReportChooseOption((TLRPC.TL_reportResultAddComment) response); + } + sheet.setListener(new ReportBottomSheet.Listener() { + @Override + public void onReported() { + if (!done[0] && whenDone != null) { + done[0] = true; + whenDone.run(true); + } + AndroidUtilities.runOnUIThread(() -> { + if (LaunchActivity.getSafeLastFragment() == null) return; + final BulletinFactory bf = bulletinFactory == null ? BulletinFactory.of(LaunchActivity.getSafeLastFragment()) : bulletinFactory; + if (bf == null) return; + bf + .createSimpleBulletin( + R.raw.msg_antispam, + LocaleController.getString(R.string.ReportChatSent), + LocaleController.getString(R.string.Reported2) + ) + .setDuration(Bulletin.DURATION_PROLONG) + .show(); + }, 200); + } + }); + sheet.setOnDismissListener(() -> { + if (!done[0] && whenDone != null) { + done[0] = true; + whenDone.run(false); + } + }); + sheet.show(); + }); + } else if (response instanceof TLRPC.TL_reportResultReported) { + AndroidUtilities.runOnUIThread(() -> { + if (!done[0] && whenDone != null) { + done[0] = true; + whenDone.run(true); + } + if (LaunchActivity.getSafeLastFragment() == null) return; + final BulletinFactory bf = bulletinFactory == null ? BulletinFactory.of(LaunchActivity.getSafeLastFragment()) : bulletinFactory; + if (bf == null) return; + bf + .createSimpleBulletin( + R.raw.msg_antispam, + LocaleController.getString(R.string.ReportChatSent), + LocaleController.getString(R.string.Reported2) + ) + .setDuration(Bulletin.DURATION_PROLONG) + .show(); + }, 200); + } + } + }); + } + + public static void openSponsored( + ChatActivity fragment, + MessageObject message, + Theme.ResourcesProvider resourceProvider + ) { + if (fragment == null) return; + final int currentAccount = fragment.getCurrentAccount(); + final Context context = fragment.getContext(); + final long dialogId = fragment.getDialogId(); + if (context == null) return; + + TLRPC.TL_channels_reportSponsoredMessage req = new TLRPC.TL_channels_reportSponsoredMessage(); + req.channel = MessagesController.getInstance(currentAccount).getInputChannel(-dialogId); + final byte[] sponsoredId = req.random_id = message.sponsoredId; + req.option = new byte[]{}; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (response != null) { + if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) { + AndroidUtilities.runOnUIThread(() -> { + TLRPC.TL_channels_sponsoredMessageReportResultChooseOption result = (TLRPC.TL_channels_sponsoredMessageReportResultChooseOption) response; + new ReportBottomSheet(context, resourceProvider, dialogId, sponsoredId) + .setReportChooseOption(result) + .setListener(new ReportBottomSheet.Listener() { + @Override + public void onReported() { + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.of(fragment) + .createAdReportedBulletin( + AndroidUtilities.replaceSingleTag( + LocaleController.getString(R.string.AdReported), + -1, + AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, + () -> Browser.openUrl(context, "https://promote.telegram.org/guidelines"), + resourceProvider + ) + ) + .show(); + fragment.removeFromSponsored(message); + fragment.removeMessageWithThanos(message); + }, 200); + } + + @Override + public void onHidden() { + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.of(fragment) + .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) + .show(); + fragment.removeFromSponsored(message); + fragment.removeMessageWithThanos(message); + }, 200); + } + + @Override + public void onPremiumRequired() { + fragment.showDialog(new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + } + }) + .show(); + }); + } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultReported) { + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.of(fragment) + .createAdReportedBulletin( + AndroidUtilities.replaceSingleTag( + LocaleController.getString(R.string.AdReported), + -1, + AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, + () -> Browser.openUrl(context, "https://promote.telegram.org/guidelines"), + resourceProvider + ) + ) + .show(); + fragment.removeFromSponsored(message); + fragment.removeMessageWithThanos(message); + }, 200); + } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultAdsHidden) { + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.of(fragment) + .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) + .show(); + MessagesController.getInstance(currentAccount).disableAds(false); + fragment.removeFromSponsored(message); + fragment.removeMessageWithThanos(message); + }, 200); + } + } else if (error != null && "AD_EXPIRED".equalsIgnoreCase(error.text)) { + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.of(fragment) + .createAdReportedBulletin( + AndroidUtilities.replaceSingleTag( + LocaleController.getString(R.string.AdReported), + -1, + AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, + () -> Browser.openUrl(context, "https://promote.telegram.org/guidelines"), + resourceProvider + ) + ) + .show(); + fragment.removeFromSponsored(message); + fragment.removeMessageWithThanos(message); + }, 200); + } + }); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java index 3351ee23a0..29cdee73d6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java @@ -432,6 +432,7 @@ public void setBounds(@NonNull Rect bounds) { private float animateToClipHorizontal; private int[] animateFromRadius; private boolean animateToRadius; + @Keep private float animationValue; private int currentRotation; private long animationStartTime; @@ -886,6 +887,7 @@ public void setAlpha(float alpha) { actionBar.setBackgroundColor(Theme.ACTION_BAR_PHOTO_VIEWER_COLOR); actionBar.setOccupyStatusBar(Build.VERSION.SDK_INT >= 21); actionBar.setItemsBackgroundColor(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, false); + actionBar.setItemsColor(Color.WHITE, false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setTitleRightMargin(dp(70)); containerView.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -1611,7 +1613,7 @@ public void openMedia(MessageObject messageObject, PhotoViewer.PhotoViewerProvid ObjectAnimator.ofFloat(captionScrollView, View.ALPHA, 0, 1f), ObjectAnimator.ofFloat(secretHint, View.ALPHA, 0, 1.0f), ObjectAnimator.ofInt(photoBackgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0, 255), - ObjectAnimator.ofFloat(this, "animationValue", 0, 1), + ObjectAnimator.ofFloat(this, ANIMATION_VALUE, 0, 1), ObjectAnimator.ofFloat(seekbarContainer, seekbarContainer.SEEKBAR_ALPHA, 1.0f), ObjectAnimator.ofFloat(seekbarContainer, View.ALPHA, isVideo ? 1f : 0f) ); @@ -1946,6 +1948,18 @@ private void onDraw(Canvas canvas) { canvas.restore(); } + public final Property VIDEO_CROSSFADE_ALPHA = new AnimationProperties.FloatProperty("videoCrossfadeAlpha") { + @Override + public void setValue(SecretMediaViewer object, float value) { + object.setVideoCrossfadeAlpha(value); + } + + @Override + public Float get(SecretMediaViewer object) { + return object.getVideoCrossfadeAlpha(); + } + }; + @Keep public float getVideoCrossfadeAlpha() { return videoCrossfadeAlpha; @@ -2068,27 +2082,27 @@ public boolean closePhoto(boolean animated, boolean byDelete) { textureUploaded = false; imageMoveAnimation.playTogether( ObjectAnimator.ofInt(photoBackgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0), - ObjectAnimator.ofFloat(this, "animationValue", 0, 1), + ObjectAnimator.ofFloat(this, ANIMATION_VALUE, 0, 1), ObjectAnimator.ofFloat(actionBar, View.ALPHA, 0), ObjectAnimator.ofFloat(captionScrollView, View.ALPHA, 0), ObjectAnimator.ofFloat(navigationBar, View.ALPHA, 0), ObjectAnimator.ofFloat(seekbarContainer, seekbarContainer.SEEKBAR_ALPHA, 0f), ObjectAnimator.ofFloat(seekbarContainer, View.ALPHA, 0f), ObjectAnimator.ofFloat(secretHint, View.ALPHA, 0), - ObjectAnimator.ofFloat(this, "videoCrossfadeAlpha", 0) + ObjectAnimator.ofFloat(this, VIDEO_CROSSFADE_ALPHA, 0) ); } else { centerImage.setManualAlphaAnimator(true); imageMoveAnimation.playTogether( ObjectAnimator.ofInt(photoBackgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0), - ObjectAnimator.ofFloat(this, "animationValue", 0, 1), + ObjectAnimator.ofFloat(this, ANIMATION_VALUE, 0, 1), ObjectAnimator.ofFloat(actionBar, View.ALPHA, 0), ObjectAnimator.ofFloat(captionScrollView, View.ALPHA, 0), ObjectAnimator.ofFloat(navigationBar, View.ALPHA, 0), ObjectAnimator.ofFloat(seekbarContainer, seekbarContainer.SEEKBAR_ALPHA, 0f), ObjectAnimator.ofFloat(seekbarContainer, View.ALPHA, 0f), ObjectAnimator.ofFloat(secretHint, View.ALPHA, 0), - ObjectAnimator.ofFloat(centerImage, "currentAlpha", 0.0f) + ObjectAnimator.ofFloat(centerImage, AnimationProperties.IMAGE_RECEIVER_ALPHA, 0.0f) ); } @@ -2438,6 +2452,18 @@ public void onAnimationEnd(Animator animation) { imageMoveAnimation.start(); } + public final Property ANIMATION_VALUE = new AnimationProperties.FloatProperty("animationValue") { + @Override + public void setValue(SecretMediaViewer object, float value) { + object.setAnimationValue(value); + } + + @Override + public Float get(SecretMediaViewer object) { + return object.getAnimationValue(); + } + }; + @Keep public void setAnimationValue(float value) { animationValue = value; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsActivity.java index 32a6835604..bf5ea1ba38 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsActivity.java @@ -44,6 +44,7 @@ import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; @@ -386,7 +387,7 @@ private void fillItems(ArrayList items, UniversalAdapter adapter) { private void onItemClick(UItem item, View view, int pos, float x, float y) { if (item.instanceOf(StarsIntroActivity.StarsTransactionView.Factory.class)) { - TLRPC.StarsTransaction t = (TLRPC.StarsTransaction) item.object; + TL_stars.StarsTransaction t = (TL_stars.StarsTransaction) item.object; StarsIntroActivity.showTransactionSheet(getContext(), true, bot_id, currentAccount, t, getResourceProvider()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsController.java index e35fa9bc43..c9ccb0a853 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stars/BotStarsController.java @@ -1,51 +1,22 @@ package org.telegram.ui.Stars; -import static org.telegram.messenger.LocaleController.formatPluralString; -import static org.telegram.messenger.LocaleController.getCurrencyExpDivider; import static org.telegram.messenger.LocaleController.getString; -import android.app.Activity; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.util.LongSparseArray; - import androidx.annotation.NonNull; -import com.android.billingclient.api.BillingClient; -import com.android.billingclient.api.BillingFlowParams; -import com.android.billingclient.api.ProductDetails; -import com.android.billingclient.api.QueryProductDetailsParams; - -import org.json.JSONObject; -import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.BillingController; -import org.telegram.messenger.BuildVars; import org.telegram.messenger.DialogObject; -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.UserConfig; -import org.telegram.messenger.UserObject; -import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stats; -import org.telegram.ui.ActionBar.AlertDialog; -import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChannelMonetizationLayout; -import org.telegram.ui.Components.BulletinFactory; -import org.telegram.ui.LaunchActivity; -import org.telegram.ui.PaymentFormActivity; -import org.telegram.ui.bots.BotWebViewSheet; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; public class BotStarsController { @@ -186,7 +157,7 @@ public void onUpdate(TLRPC.TL_updateStarsRevenueStatus update) { public static final int OUTGOING_TRANSACTIONS = 2; private class TransactionsState { - public final ArrayList[] transactions = new ArrayList[] { new ArrayList<>(), new ArrayList<>(), new ArrayList<>() }; + public final ArrayList[] transactions = new ArrayList[] { new ArrayList<>(), new ArrayList<>(), new ArrayList<>() }; public final boolean[] transactionsExist = new boolean[3]; private final String[] offset = new String[3]; private final boolean[] loading = new boolean[3]; @@ -205,7 +176,7 @@ private TransactionsState getTransactionsState(long did) { } @NonNull - public ArrayList getTransactions(long did, int type) { + public ArrayList getTransactions(long did, int type) { TransactionsState state = getTransactionsState(did); return state.transactions[type]; } @@ -240,7 +211,7 @@ public void loadTransactions(long did, int type) { state.loading[type] = true; - TLRPC.TL_payments_getStarsTransactions req = new TLRPC.TL_payments_getStarsTransactions(); + TL_stars.TL_payments_getStarsTransactions req = new TL_stars.TL_payments_getStarsTransactions(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(did); req.inbound = type == INCOMING_TRANSACTIONS; req.outbound = type == OUTGOING_TRANSACTIONS; @@ -250,8 +221,8 @@ public void loadTransactions(long did, int type) { } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { state.loading[type] = false; - if (res instanceof TLRPC.TL_payments_starsStatus) { - TLRPC.TL_payments_starsStatus r = (TLRPC.TL_payments_starsStatus) res; + if (res instanceof TL_stars.TL_payments_starsStatus) { + TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res; MessagesController.getInstance(currentAccount).putUsers(r.users, false); MessagesController.getInstance(currentAccount).putChats(r.chats, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stars/ExplainStarsSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stars/ExplainStarsSheet.java new file mode 100644 index 0000000000..613113e573 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stars/ExplainStarsSheet.java @@ -0,0 +1,207 @@ +package org.telegram.ui.Stars; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.exoplayer2.scheduler.RequirementsWatcher; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.DialogsBotsAdapter; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.Premium.GLIcon.GLIconRenderer; +import org.telegram.ui.Components.Premium.GLIcon.GLIconTextureView; +import org.telegram.ui.Components.Premium.GLIcon.Icon3D; +import org.telegram.ui.Components.Premium.StarParticlesView; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.StarAppsSheet; +import org.telegram.ui.Components.UItem; +import org.telegram.ui.Components.UniversalAdapter; +import org.telegram.ui.Components.UniversalRecyclerView; +import org.telegram.ui.Gifts.GiftSheet; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; +import org.telegram.ui.Stories.recorder.HintView2; + +import java.util.ArrayList; + +public class ExplainStarsSheet extends BottomSheetWithRecyclerListView { + + private UniversalAdapter adapter; + + private LinearLayout headerView; + private FrameLayout buttonContainer; + + public ExplainStarsSheet(Context context) { + super(context, null, false, false, false, null); + topPadding = .1f; + + fixNavigationBar(); + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + + headerView = new LinearLayout(context); + headerView.setOrientation(LinearLayout.VERTICAL); + + FrameLayout topView = new FrameLayout(context); + topView.setClipChildren(false); + topView.setClipToPadding(false); + + StarParticlesView particlesView = StarsIntroActivity.makeParticlesView(context, 70, 0); + topView.addView(particlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + GLIconTextureView iconView = new GLIconTextureView(context, GLIconRenderer.DIALOG_STYLE, Icon3D.TYPE_GOLDEN_STAR); + iconView.mRenderer.colorKey1 = Theme.key_starsGradient1; + iconView.mRenderer.colorKey2 = Theme.key_starsGradient2; + iconView.mRenderer.updateColors(); + iconView.setStarParticlesView(particlesView); + topView.addView(iconView, LayoutHelper.createFrame(170, 170, Gravity.CENTER, 0, 32, 0, 24)); + iconView.setPaused(false); + + headerView.addView(topView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 150)); + + TextView titleView = new TextView(context); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTypeface(AndroidUtilities.bold()); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + titleView.setGravity(Gravity.CENTER); + titleView.setText(getString(R.string.ExplainStarsTitle)); + headerView.addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 2, 0, 0)); + + TextView subtitleView = new TextView(context); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + subtitleView.setGravity(Gravity.CENTER); + subtitleView.setText(getString(R.string.ExplainStarsTitle2)); + headerView.addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT/*(int) Math.ceil(HintView2.cutInFancyHalf(subtitleView.getText(), subtitleView.getPaint()) / AndroidUtilities.density)*/, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 16, 9, 16, 18)); + + buttonContainer = new FrameLayout(context); + ButtonWithCounterView button = new ButtonWithCounterView(context, resourcesProvider); + button.setText(getString(R.string.ExplainStarsButton), false); + button.setOnClickListener(v -> dismiss()); + buttonContainer.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 10, 10, 10, 10)); + buttonContainer.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + containerView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + + adapter.update(false); + } + + @Override + protected CharSequence getTitle() { + return getString(R.string.ExplainStarsTitle); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + return adapter = new UniversalAdapter(listView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider) { + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + }; + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + items.add(UItem.asCustom(headerView)); + items.add(FeatureCell.Factory.of(R.drawable.msg_gift_premium, getString(R.string.ExplainStarsFeature1Title), getString(R.string.ExplainStarsFeature1Text))); + items.add(FeatureCell.Factory.of(R.drawable.msg_bot, getString(R.string.ExplainStarsFeature2Title), AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.ExplainStarsFeature2Text), () -> { + new StarAppsSheet(getContext()).show(); + }), true))); + items.add(FeatureCell.Factory.of(R.drawable.menu_unlock, getString(R.string.ExplainStarsFeature3Title), getString(R.string.ExplainStarsFeature3Text))); + items.add(FeatureCell.Factory.of(R.drawable.menu_feature_paid, getString(R.string.ExplainStarsFeature4Title), getString(R.string.ExplainStarsFeature4Text))); + items.add(UItem.asSpace(dp(10 + 48 + 10))); + } + + public static class FeatureCell extends LinearLayout { + + private final ImageView imageView; + private final LinearLayout textLayout; + private final TextView titleView; + private final LinkSpanDrawable.LinksTextView subtitleView; + + public FeatureCell(Context context) { + super(context); + + setOrientation(HORIZONTAL); + + setPadding(dp(32), 0, dp(32), dp(12)); + + imageView = new ImageView(context); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); + imageView.setScaleType(ImageView.ScaleType.CENTER); + addView(imageView, LayoutHelper.createLinear(24, 24, Gravity.TOP | Gravity.LEFT, 0, 6, 16, 0)); + + textLayout = new LinearLayout(context); + textLayout.setOrientation(VERTICAL); + + titleView = new TextView(context); + titleView.setTypeface(AndroidUtilities.bold()); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textLayout.addView(titleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL, 0, 0, 0, 3)); + + subtitleView = new LinkSpanDrawable.LinksTextView(context); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + subtitleView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn)); + textLayout.addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL)); + + addView(textLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 1f, Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0, 0, 0)); + } + + public void set(int iconResId, CharSequence title, CharSequence text) { + imageView.setImageResource(iconResId); + titleView.setText(title); + subtitleView.setText(text); + } + + public static class Factory extends UItem.UItemFactory { + static { setup(new Factory()); } + + @Override + public FeatureCell createView(Context context, int currentAccount, int classGuid, Theme.ResourcesProvider resourcesProvider) { + return new FeatureCell(context); + } + + @Override + public void bindView(View view, UItem item, boolean divider) { + ((FeatureCell) view).set( + item.intValue, item.text, item.subtext + ); + } + + public static UItem of(int iconResId, CharSequence title, CharSequence text) { + UItem item = UItem.ofFactory(Factory.class); + item.selectable = false; + item.intValue = iconResId; + item.text = title; + item.subtext = text; + return item; + } + + } + } + + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsController.java index b05cb8b2bc..cb401eaa88 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsController.java @@ -9,6 +9,8 @@ import android.content.Context; import android.content.SharedPreferences; import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.LongSparseArray; import android.view.Gravity; import androidx.annotation.Nullable; @@ -19,16 +21,21 @@ import com.android.billingclient.api.QueryProductDetailsParams; import org.json.JSONObject; +import org.telegram.SQLite.SQLiteCursor; +import org.telegram.SQLite.SQLiteDatabase; +import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BillingController; import org.telegram.messenger.BuildVars; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.FileLog; import org.telegram.messenger.FileRefController; 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; @@ -36,8 +43,10 @@ import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -91,6 +100,8 @@ private StarsController(int account) { currentAccount = account; } + // ===== STAR BALANCE ===== + private long lastBalanceLoaded; private boolean balanceLoading, balanceLoaded; public long balance; @@ -111,20 +122,20 @@ public long getBalance(Runnable loaded) { public long getBalance(boolean withMinus, Runnable loaded) { if ((!balanceLoaded || System.currentTimeMillis() - lastBalanceLoaded > 1000 * 60) && !balanceLoading) { balanceLoading = true; - TLRPC.TL_payments_getStarsStatus req = new TLRPC.TL_payments_getStarsStatus(); + TL_stars.TL_payments_getStarsStatus req = new TL_stars.TL_payments_getStarsStatus(); req.peer = new TLRPC.TL_inputPeerSelf(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { boolean updatedTransactions = false; boolean updatedSubscriptions = false; boolean updatedBalance = !balanceLoaded; lastBalanceLoaded = System.currentTimeMillis(); - if (res instanceof TLRPC.TL_payments_starsStatus) { - TLRPC.TL_payments_starsStatus r = (TLRPC.TL_payments_starsStatus) res; + if (res instanceof TL_stars.TL_payments_starsStatus) { + TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res; MessagesController.getInstance(currentAccount).putUsers(r.users, false); MessagesController.getInstance(currentAccount).putChats(r.chats, false); if (transactions[ALL_TRANSACTIONS].isEmpty()) { - for (TLRPC.StarsTransaction t : r.history) { + for (TL_stars.StarsTransaction t : r.history) { transactions[ALL_TRANSACTIONS].add(t); transactions[t.stars > 0 ? INCOMING_TRANSACTIONS : OUTGOING_TRANSACTIONS].add(t); } @@ -195,24 +206,24 @@ public boolean balanceAvailable() { } private boolean optionsLoading, optionsLoaded; - private ArrayList options; - public ArrayList getOptionsCached() { + private ArrayList options; + public ArrayList getOptionsCached() { return options; } - public ArrayList getOptions() { + public ArrayList getOptions() { if (optionsLoading || optionsLoaded) { return options; } optionsLoading = true; - ConnectionsManager.getInstance(currentAccount).sendRequest(new TLRPC.TL_payments_getStarsTopupOptions(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { - ArrayList loadedOptions = new ArrayList<>(); - ArrayList toLoadStorePrice = new ArrayList<>(); + ConnectionsManager.getInstance(currentAccount).sendRequest(new TL_stars.TL_payments_getStarsTopupOptions(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { + ArrayList loadedOptions = new ArrayList<>(); + ArrayList toLoadStorePrice = new ArrayList<>(); if (res instanceof TLRPC.Vector) { TLRPC.Vector vector = (TLRPC.Vector) res; for (Object object : vector.objects) { - if (object instanceof TLRPC.TL_starsTopupOption) { - TLRPC.TL_starsTopupOption option = (TLRPC.TL_starsTopupOption) object; + if (object instanceof TL_stars.TL_starsTopupOption) { + TL_stars.TL_starsTopupOption option = (TL_stars.TL_starsTopupOption) object; loadedOptions.add(option); if (option.store_product != null && !BuildVars.useInvoiceBilling()) { toLoadStorePrice.add(option); @@ -244,7 +255,7 @@ public ArrayList getOptions() { if (list != null) { for (int i = 0; i < list.size(); ++i) { ProductDetails productDetails = list.get(i); - TLRPC.TL_starsTopupOption option = null; + TL_stars.TL_starsTopupOption option = null; for (int j = 0; j < toLoadStorePrice.size(); ++j) { if (toLoadStorePrice.get(j).store_product.equals(productDetails.getProductId())) { option = toLoadStorePrice.get(j); @@ -263,7 +274,7 @@ public ArrayList getOptions() { } if (options != null) { for (int i = 0; i < options.size(); ++i) { - TLRPC.TL_starsTopupOption option = options.get(i); + TL_stars.TL_starsTopupOption option = options.get(i); if (option != null && option.loadingStorePrice) { option.missingStorePrice = true; } @@ -283,24 +294,24 @@ public ArrayList getOptions() { } private boolean giftOptionsLoading, giftOptionsLoaded; - private ArrayList giftOptions; - public ArrayList getGiftOptionsCached() { + private ArrayList giftOptions; + public ArrayList getGiftOptionsCached() { return giftOptions; } - public ArrayList getGiftOptions() { + public ArrayList getGiftOptions() { if (giftOptionsLoading || giftOptionsLoaded) { return giftOptions; } giftOptionsLoading = true; - TLRPC.TL_payments_getStarsGiftOptions req = new TLRPC.TL_payments_getStarsGiftOptions(); + TL_stars.TL_payments_getStarsGiftOptions req = new TL_stars.TL_payments_getStarsGiftOptions(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - ArrayList loadedOptions = new ArrayList<>(); - ArrayList toLoadStorePrice = new ArrayList<>(); + ArrayList loadedOptions = new ArrayList<>(); + ArrayList toLoadStorePrice = new ArrayList<>(); if (res instanceof TLRPC.Vector) { TLRPC.Vector vector = (TLRPC.Vector) res; for (Object object : vector.objects) { - if (object instanceof TLRPC.TL_starsGiftOption) { - TLRPC.TL_starsGiftOption option = (TLRPC.TL_starsGiftOption) object; + if (object instanceof TL_stars.TL_starsGiftOption) { + TL_stars.TL_starsGiftOption option = (TL_stars.TL_starsGiftOption) object; loadedOptions.add(option); if (option.store_product != null && !BuildVars.useInvoiceBilling()) { toLoadStorePrice.add(option); @@ -332,7 +343,7 @@ public ArrayList getGiftOptions() { if (list != null) { for (int i = 0; i < list.size(); ++i) { ProductDetails productDetails = list.get(i); - TLRPC.TL_starsGiftOption option = null; + TL_stars.TL_starsGiftOption option = null; for (int j = 0; j < toLoadStorePrice.size(); ++j) { if (toLoadStorePrice.get(j).store_product.equals(productDetails.getProductId())) { option = toLoadStorePrice.get(j); @@ -351,7 +362,7 @@ public ArrayList getGiftOptions() { } if (giftOptions != null) { for (int i = 0; i < giftOptions.size(); ++i) { - TLRPC.TL_starsGiftOption option = giftOptions.get(i); + TL_stars.TL_starsGiftOption option = giftOptions.get(i); if (option != null && option.loadingStorePrice) { option.missingStorePrice = true; } @@ -371,24 +382,24 @@ public ArrayList getGiftOptions() { } private boolean giveawayOptionsLoading, giveawayOptionsLoaded; - private ArrayList giveawayOptions; - public ArrayList getGiveawayOptionsCached() { + private ArrayList giveawayOptions; + public ArrayList getGiveawayOptionsCached() { return giveawayOptions; } - public ArrayList getGiveawayOptions() { + public ArrayList getGiveawayOptions() { if (giveawayOptionsLoading || giveawayOptionsLoaded) { return giveawayOptions; } giveawayOptionsLoading = true; - TLRPC.TL_payments_getStarsGiveawayOptions req = new TLRPC.TL_payments_getStarsGiveawayOptions(); + TL_stars.TL_payments_getStarsGiveawayOptions req = new TL_stars.TL_payments_getStarsGiveawayOptions(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - ArrayList loadedOptions = new ArrayList<>(); - ArrayList toLoadStorePrice = new ArrayList<>(); + ArrayList loadedOptions = new ArrayList<>(); + ArrayList toLoadStorePrice = new ArrayList<>(); if (res instanceof TLRPC.Vector) { TLRPC.Vector vector = (TLRPC.Vector) res; for (Object object : vector.objects) { - if (object instanceof TLRPC.TL_starsGiveawayOption) { - TLRPC.TL_starsGiveawayOption option = (TLRPC.TL_starsGiveawayOption) object; + if (object instanceof TL_stars.TL_starsGiveawayOption) { + TL_stars.TL_starsGiveawayOption option = (TL_stars.TL_starsGiveawayOption) object; loadedOptions.add(option); if (option.store_product != null && !BuildVars.useInvoiceBilling()) { toLoadStorePrice.add(option); @@ -420,7 +431,7 @@ public ArrayList getGiveawayOptions() { if (list != null) { for (int i = 0; i < list.size(); ++i) { ProductDetails productDetails = list.get(i); - TLRPC.TL_starsGiveawayOption option = null; + TL_stars.TL_starsGiveawayOption option = null; for (int j = 0; j < toLoadStorePrice.size(); ++j) { if (toLoadStorePrice.get(j).store_product.equals(productDetails.getProductId())) { option = toLoadStorePrice.get(j); @@ -439,7 +450,7 @@ public ArrayList getGiveawayOptions() { } if (giveawayOptions != null) { for (int i = 0; i < giveawayOptions.size(); ++i) { - TLRPC.TL_starsGiveawayOption option = giveawayOptions.get(i); + TL_stars.TL_starsGiveawayOption option = giveawayOptions.get(i); if (option != null && option.loadingStorePrice) { option.missingStorePrice = true; } @@ -467,11 +478,15 @@ private void bulletinError(String err) { b.createSimpleBulletin(R.raw.error, formatString(R.string.UnknownErrorCode, err)).show(); } + + + // ===== STAR TRANSACTIONS ===== + public static final int ALL_TRANSACTIONS = 0; public static final int INCOMING_TRANSACTIONS = 1; public static final int OUTGOING_TRANSACTIONS = 2; - public final ArrayList[] transactions = new ArrayList[] { new ArrayList<>(), new ArrayList<>(), new ArrayList<>() }; + public final ArrayList[] transactions = new ArrayList[] { new ArrayList<>(), new ArrayList<>(), new ArrayList<>() }; public final boolean[] transactionsExist = new boolean[3]; private final String[] offset = new String[3]; private final boolean[] loading = new boolean[3]; @@ -488,7 +503,6 @@ public void invalidateTransactions(boolean load) { loadTransactions(i); } } - public void preloadTransactions() { for (int i = 0; i < 3; ++i) { if (!loading[i] && !endReached[i] && offset[i] == null) { @@ -496,7 +510,6 @@ public void preloadTransactions() { } } } - public void loadTransactions(int type) { if (loading[type] || endReached[type]) { return; @@ -504,7 +517,7 @@ public void loadTransactions(int type) { loading[type] = true; - TLRPC.TL_payments_getStarsTransactions req = new TLRPC.TL_payments_getStarsTransactions(); + TL_stars.TL_payments_getStarsTransactions req = new TL_stars.TL_payments_getStarsTransactions(); req.peer = new TLRPC.TL_inputPeerSelf(); req.inbound = type == INCOMING_TRANSACTIONS; req.outbound = type == OUTGOING_TRANSACTIONS; @@ -514,8 +527,8 @@ public void loadTransactions(int type) { } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { loading[type] = false; - if (res instanceof TLRPC.TL_payments_starsStatus) { - TLRPC.TL_payments_starsStatus r = (TLRPC.TL_payments_starsStatus) res; + if (res instanceof TL_stars.TL_payments_starsStatus) { + TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res; MessagesController.getInstance(currentAccount).putUsers(r.users, false); MessagesController.getInstance(currentAccount).putChats(r.chats, false); @@ -529,15 +542,12 @@ public void loadTransactions(int type) { } })); } - public boolean isLoadingTransactions(int type) { return loading[type]; } - public boolean didFullyLoadTransactions(int type) { return endReached[type]; } - public boolean hasTransactions() { return hasTransactions(ALL_TRANSACTIONS); } @@ -545,7 +555,11 @@ public boolean hasTransactions(int type) { return balanceAvailable() && !transactions[type].isEmpty(); } - public final ArrayList subscriptions = new ArrayList<>(); + + + // ===== STAR SUBSCRIPTIONS ===== + + public final ArrayList subscriptions = new ArrayList<>(); public String subscriptionsOffset; public boolean subscriptionsLoading, subscriptionsEndReached; @@ -565,7 +579,7 @@ public void invalidateSubscriptions(boolean load) { public void loadSubscriptions() { if (subscriptionsLoading || subscriptionsEndReached) return; subscriptionsLoading = true; - TLRPC.TL_getStarsSubscriptions req = new TLRPC.TL_getStarsSubscriptions(); + TL_stars.TL_getStarsSubscriptions req = new TL_stars.TL_getStarsSubscriptions(); req.peer = new TLRPC.TL_inputPeerSelf(); req.offset = subscriptionsOffset; if (req.offset == null) { @@ -573,8 +587,8 @@ public void loadSubscriptions() { } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { subscriptionsLoading = false; - if (res instanceof TLRPC.TL_payments_starsStatus) { - TLRPC.TL_payments_starsStatus r = (TLRPC.TL_payments_starsStatus) res; + if (res instanceof TL_stars.TL_payments_starsStatus) { + TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res; MessagesController.getInstance(currentAccount).putUsers(r.users, false); MessagesController.getInstance(currentAccount).putChats(r.chats, false); @@ -594,20 +608,19 @@ public boolean didFullyLoadSubscriptions() { return subscriptionsEndReached; } - - public final ArrayList insufficientSubscriptions = new ArrayList<>(); + public final ArrayList insufficientSubscriptions = new ArrayList<>(); private boolean insufficientSubscriptionsLoading; public void loadInsufficientSubscriptions() { if (insufficientSubscriptionsLoading) return; insufficientSubscriptionsLoading = true; - TLRPC.TL_getStarsSubscriptions req = new TLRPC.TL_getStarsSubscriptions(); + TL_stars.TL_getStarsSubscriptions req = new TL_stars.TL_getStarsSubscriptions(); req.peer = new TLRPC.TL_inputPeerSelf(); req.missing_balance = true; req.offset = ""; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { insufficientSubscriptionsLoading = false; - if (res instanceof TLRPC.TL_payments_starsStatus) { - TLRPC.TL_payments_starsStatus r = (TLRPC.TL_payments_starsStatus) res; + if (res instanceof TL_stars.TL_payments_starsStatus) { + TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res; MessagesController.getInstance(currentAccount).putUsers(r.users, false); MessagesController.getInstance(currentAccount).putChats(r.chats, false); insufficientSubscriptions.addAll(r.subscriptions); @@ -626,6 +639,7 @@ public boolean hasInsufficientSubscriptions() { return !insufficientSubscriptions.isEmpty(); } + public Theme.ResourcesProvider getResourceProvider() { BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); if (lastFragment != null) { @@ -660,7 +674,7 @@ private void showStarsTopupInternal(Activity activity, long amount, String purpo }).show(); } - public void buy(Activity activity, TLRPC.TL_starsTopupOption option, Utilities.Callback2 whenDone) { + public void buy(Activity activity, TL_stars.TL_starsTopupOption option, Utilities.Callback2 whenDone) { if (activity == null) { return; } @@ -787,7 +801,7 @@ public void buy(Activity activity, TLRPC.TL_starsTopupOption option, Utilities.C })); } - public void buyGift(Activity activity, TLRPC.TL_starsGiftOption option, long user_id, Utilities.Callback2 whenDone) { + public void buyGift(Activity activity, TL_stars.TL_starsGiftOption option, long user_id, Utilities.Callback2 whenDone) { if (activity == null) { return; } @@ -927,15 +941,15 @@ public void buyGift(Activity activity, TLRPC.TL_starsGiftOption option, long use } public void buyGiveaway( - Activity activity, - TLRPC.Chat chat, List chats, - TLRPC.TL_starsGiveawayOption option, int users, - List countries, - int date, - boolean winnersVisible, - boolean onlyNewSubscribers, - boolean withAdditionPrize, String prizeDescription, - Utilities.Callback2 whenDone + Activity activity, + TLRPC.Chat chat, List chats, + TL_stars.TL_starsGiveawayOption option, int users, + List countries, + int date, + boolean winnersVisible, + boolean onlyNewSubscribers, + boolean withAdditionPrize, String prizeDescription, + Utilities.Callback2 whenDone ) { if (activity == null) { return; @@ -1362,7 +1376,7 @@ private void payAfterConfirmed(MessageObject messageObject, TLRPC.InputInvoice i } final String product = form.title; - TLRPC.TL_payments_sendStarsForm req2 = new TLRPC.TL_payments_sendStarsForm(); + TL_stars.TL_payments_sendStarsForm req2 = new TL_stars.TL_payments_sendStarsForm(); req2.form_id = form.form_id; req2.invoice = inputInvoice; ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (res2, err2) -> AndroidUtilities.runOnUIThread(() -> { @@ -1475,7 +1489,7 @@ private void payAfterConfirmed(String hash, TLRPC.ChatInvite chatInvite, Utiliti TLRPC.TL_inputInvoiceChatInviteSubscription inputInvoice = new TLRPC.TL_inputInvoiceChatInviteSubscription(); inputInvoice.hash = hash; - TLRPC.TL_payments_sendStarsForm req2 = new TLRPC.TL_payments_sendStarsForm(); + TL_stars.TL_payments_sendStarsForm req2 = new TL_stars.TL_payments_sendStarsForm(); req2.form_id = chatInvite.subscription_form_id; req2.invoice = inputInvoice; ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (res2, err2) -> AndroidUtilities.runOnUIThread(() -> { @@ -1628,6 +1642,10 @@ private void updateMediaPrice(MessageObject msg, long price, Runnable done, bool })); } + + + // ===== STAR REACTIONS ===== + public static final long REACTIONS_TIMEOUT = 5_000; public PendingPaidReactions currentPendingReactions; @@ -2054,4 +2072,404 @@ public long getPendingPaidReactions(long dialogId, int messageId) { if (!currentPendingReactions.applied) return 0; return currentPendingReactions.amount; } + + + // ===== STAR GIFTS ===== + + public boolean giftsLoading, giftsLoaded; + private boolean giftsCacheLoaded; + public int giftsHash; + public long giftsRemoteTime; + public final ArrayList gifts = new ArrayList<>(); + + public void invalidateStarGifts() { + giftsLoaded = false; + giftsCacheLoaded = true; + giftsRemoteTime = 0; + loadStarGifts(); + } + + public void loadStarGifts() { + if (giftsLoading || giftsLoaded && (System.currentTimeMillis() - giftsRemoteTime) < 1000 * 60 * 5) return; + giftsLoading = true; + + final SharedPreferences prefs = MessagesController.getInstance(currentAccount).getMainSettings(); + + if (!giftsCacheLoaded) { + getStarGiftsCached((giftsCached, hash, time) -> { + giftsCacheLoaded = true; + gifts.clear(); + gifts.addAll(giftsCached); + giftsHash = hash; + giftsRemoteTime = time; + giftsLoading = false; + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.starGiftsLoaded); + + loadStarGifts(); + }); + } else { + getStarGiftsRemote(giftsHash, giftsRemote -> { + giftsLoading = false; + giftsLoaded = true; + if (giftsRemote instanceof TL_stars.TL_starGifts) { + final TL_stars.TL_starGifts res = (TL_stars.TL_starGifts) giftsRemote; + gifts.clear(); + gifts.addAll(res.gifts); + giftsHash = res.hash; + giftsRemoteTime = System.currentTimeMillis(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.starGiftsLoaded); + saveStarGiftsCached(res.gifts, giftsHash, giftsRemoteTime); + } else if (giftsRemote instanceof TL_stars.TL_starGiftsNotModified) { + saveStarGiftsCached(gifts, giftsHash, giftsRemoteTime = System.currentTimeMillis()); + } + }); + } + } + + public void makeStarGiftSoldOut(TL_stars.StarGift starGift) { + if (starGift == null || !giftsLoaded) return; + starGift.availability_remains = 0; + saveStarGiftsCached(gifts, giftsHash, giftsRemoteTime); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.starGiftSoldOut, starGift); + } + + private void getStarGiftsCached(Utilities.Callback3, Integer, Long> whenDone) { + if (whenDone == null) return; + final ArrayList result = new ArrayList<>(); + final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); + storage.getStorageQueue().postRunnable(() -> { + final SQLiteDatabase db = storage.getDatabase(); + int hash = 0; + long time = 0; + SQLiteCursor cursor = null; + try { + cursor = db.queryFinalized("SELECT data, hash, time FROM star_gifts2 ORDER BY pos ASC"); + while (cursor.next()) { + final NativeByteBuffer data = cursor.byteBufferValue(0); + if (data != null) { + TL_stars.StarGift gift = TL_stars.StarGift.TLdeserialize(data, data.readInt32(false), false); + if (gift != null) { + result.add(gift); + } + data.reuse(); + hash = (int) cursor.longValue(1); + time = cursor.longValue(2); + } + } + } catch (Exception e) { + FileLog.e(e); + } finally { + if (cursor != null) { + cursor.dispose(); + } + } + final int finalHash = hash; + final long finalTime = time; + AndroidUtilities.runOnUIThread(() -> { + whenDone.run(result, finalHash, finalTime); + }); + }); + } + private void saveStarGiftsCached(ArrayList gifts, int hash, long time) { + final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); + storage.getStorageQueue().postRunnable(() -> { + final SQLiteDatabase db = storage.getDatabase(); + SQLitePreparedStatement state = null; + try { + db.executeFast("DELETE FROM star_gifts2").stepThis().dispose(); + if (gifts != null) { + state = db.executeFast("REPLACE INTO star_gifts2 VALUES(?, ?, ?, ?, ?)"); + for (int i = 0; i < gifts.size(); ++i) { + final TL_stars.StarGift gift = gifts.get(i); + state.requery(); + state.bindLong(1, gift.id); + NativeByteBuffer data = new NativeByteBuffer(gift.getObjectSize()); + gift.serializeToStream(data); + state.bindByteBuffer(2, data); + state.bindLong(3, hash); + state.bindLong(4, time); + state.bindInteger(5, i); + state.step(); + data.reuse(); + } + } + } catch (Exception e) { + FileLog.e(e); + } finally { + if (state != null) { + state.dispose(); + } + } + }); + } + private void getStarGiftsRemote(int hash, Utilities.Callback whenDone) { + if (whenDone == null) return; + TL_stars.getStarGifts req = new TL_stars.getStarGifts(); + req.hash = hash; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TL_stars.StarGifts) { + whenDone.run((TL_stars.StarGifts) res); + } else { + whenDone.run(null); + } + })); + } + + @Nullable + public TL_stars.StarGift getStarGift(long gift_id) { + loadStarGifts(); + for (int i = 0; i < gifts.size(); ++i) { + final TL_stars.StarGift gift = gifts.get(i); + if (gift.id == gift_id) + return gift; + } + return null; + } + + public Runnable getStarGift(long gift_id, Utilities.Callback whenDone) { +// final AlertDialog progressDialog = new AlertDialog(ApplicationLoader.applicationContext, AlertDialog.ALERT_TYPE_SPINNER); +// progressDialog.showDelayed(500); + + final boolean[] done = new boolean[] { false }; + NotificationCenter.NotificationCenterDelegate[] observer = new NotificationCenter.NotificationCenterDelegate[1]; + observer[0] = (id, account, args) -> { + if (done[0]) return; + if (id == NotificationCenter.starGiftsLoaded) { + TL_stars.StarGift gift = getStarGift(gift_id); + if (gift != null) { +// progressDialog.dismissUnless(500); + done[0] = true; + NotificationCenter.getInstance(currentAccount).removeObserver(observer[0], NotificationCenter.starGiftsLoaded); + whenDone.run(gift); + } + } + }; + NotificationCenter.getInstance(currentAccount).addObserver(observer[0], NotificationCenter.starGiftsLoaded); + TL_stars.StarGift gift = getStarGift(gift_id); + if (gift != null) { + done[0] = true; +// progressDialog.dismissUnless(500); + NotificationCenter.getInstance(currentAccount).removeObserver(observer[0], NotificationCenter.starGiftsLoaded); + whenDone.run(gift); + } + return () -> { + done[0] = true; +// progressDialog.dismissUnless(500); + NotificationCenter.getInstance(currentAccount).removeObserver(observer[0], NotificationCenter.starGiftsLoaded); + }; + } + + public void buyStarGift(Activity activity, TL_stars.StarGift gift, boolean anonymous, long user_id, TLRPC.TL_textWithEntities text, Utilities.Callback2 whenDone) { + final Context context = LaunchActivity.instance != null ? LaunchActivity.instance : ApplicationLoader.applicationContext; + final Theme.ResourcesProvider resourcesProvider = getResourceProvider(); + + if (gift == null || context == null) { + return; + } + + if (!balanceAvailable()) { + getBalance(() -> { + if (!balanceAvailable()) { + bulletinError("NO_BALANCE"); + if (whenDone != null) { + whenDone.run(false, null); + } + return; + } + buyStarGift(activity, gift, anonymous, user_id, text, whenDone); + }); + return; + } + + final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(user_id); + if (user == null) { + if (whenDone != null) { + whenDone.run(false, null); + } + return; + } + + TLRPC.TL_inputInvoiceStarGift inputInvoice = new TLRPC.TL_inputInvoiceStarGift(); + inputInvoice.hide_name = anonymous; + inputInvoice.user_id = MessagesController.getInstance(currentAccount).getInputPeer(user); + inputInvoice.gift_id = gift.id; + if (text != null && !TextUtils.isEmpty(text.text)) { + inputInvoice.flags |= 2; + inputInvoice.message = text; + } + + TLRPC.TL_payments_getPaymentForm req = new TLRPC.TL_payments_getPaymentForm(); + final JSONObject themeParams = BotWebViewSheet.makeThemeParams(resourcesProvider); + if (themeParams != null) { + req.theme_params = new TLRPC.TL_dataJSON(); + req.theme_params.data = themeParams.toString(); + req.flags |= 1; + } + req.invoice = inputInvoice; + + final int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (!(res instanceof TLRPC.TL_payments_paymentFormStarGift)) { + bulletinError(err, "NO_PAYMENT_FORM"); + whenDone.run(false, null); + return; + } + + final TLRPC.TL_payments_paymentFormStarGift form = (TLRPC.TL_payments_paymentFormStarGift) res; + TL_stars.TL_payments_sendStarsForm req2 = new TL_stars.TL_payments_sendStarsForm(); + req2.form_id = form.form_id; + req2.invoice = inputInvoice; + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (res2, err2) -> AndroidUtilities.runOnUIThread(() -> { + final BaseFragment fragment = LaunchActivity.getLastFragment(); + BulletinFactory b = fragment != null && fragment.visibleDialog == null ? BulletinFactory.of(fragment) : BulletinFactory.global(); + + if (!(res2 instanceof TLRPC.TL_payments_paymentResult)) { + if (err2 != null && "BALANCE_TOO_LOW".equals(err2.text)) { + if (!MessagesController.getInstance(currentAccount).starsPurchaseAvailable()) { + if (whenDone != null) { + whenDone.run(false, null); + } + showNoSupportDialog(context, resourcesProvider); + return; + } + final boolean[] purchased = new boolean[] { false }; + StarsIntroActivity.StarsNeededSheet sheet = new StarsIntroActivity.StarsNeededSheet(context, resourcesProvider, gift.stars, StarsIntroActivity.StarsNeededSheet.TYPE_STAR_GIFT_BUY, UserObject.getForcedFirstName(user), () -> { + purchased[0] = true; + buyStarGift(activity, gift, anonymous, user_id, text, whenDone); + }); + sheet.setOnDismissListener(d -> { + if (whenDone != null && !purchased[0]) { + whenDone.run(false, null); + } + }); + sheet.show(); + } else if (err2 != null && "STARGIFT_USAGE_LIMITED".equals(err2.text)) { + if (whenDone != null) { + whenDone.run(false, "STARGIFT_USAGE_LIMITED"); + } + } else { + if (whenDone != null) { + whenDone.run(false, null); + } + b.createSimpleBulletin(R.raw.error, formatString(R.string.UnknownErrorCode, err2 != null ? err2.text : "FAILED_SEND_STARS")).show(); + } + return; + } + + final TLRPC.TL_payments_paymentResult result = (TLRPC.TL_payments_paymentResult) res2; + MessagesController.getInstance(currentAccount).processUpdates(result.updates, false); + + if (whenDone != null) { + whenDone.run(true, null); + } + + if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getDialogId() == user_id) { + BulletinFactory.of(fragment).createEmojiBulletin(gift.sticker, getString(R.string.StarsGiftCompleted), AndroidUtilities.replaceTags(formatPluralString("StarsGiftCompletedText", (int) gift.stars/*, UserObject.getForcedFirstName(user)*/))).show(true); + } else { + final ChatActivity chatActivity = ChatActivity.of(user_id); + chatActivity.whenFullyVisible(() -> { + BulletinFactory.of(chatActivity).createEmojiBulletin(gift.sticker, getString(R.string.StarsGiftCompleted), AndroidUtilities.replaceTags(formatPluralString("StarsGiftCompletedText", (int) gift.stars/*, UserObject.getForcedFirstName(user)*/))).show(true); + }); + fragment.presentFragment(chatActivity); + } + if (LaunchActivity.instance != null && LaunchActivity.instance.getFireworksOverlay() != null) { + LaunchActivity.instance.getFireworksOverlay().start(true); + } + + invalidateStarGifts(); + invalidateTransactions(true); + })); + })); + } + + public final LongSparseArray giftLists = new LongSparseArray<>(); + public GiftsList getProfileGiftsList(long dialogId) { + return getProfileGiftsList(dialogId, true); + } + public GiftsList getProfileGiftsList(long dialogId, boolean create) { + GiftsList list = giftLists.get(dialogId); + if (list == null && create) { + giftLists.put(dialogId, list = new GiftsList(dialogId)); + } + return list; + } + + public void invalidateProfileGifts(long dialogId) { + GiftsList list = getProfileGiftsList(dialogId, false); + if (list != null) { + list.invalidate(false); + } + } + + public void invalidateProfileGifts(TLRPC.UserFull userFull) { + if (userFull == null) return; + long dialogId = userFull.id; + GiftsList list = getProfileGiftsList(dialogId, false); + if (list != null && list.totalCount != userFull.stargifts_count) { + list.invalidate(false); + } + } + + public class GiftsList { + + public final long dialogId; + public GiftsList(long dialogId) { + this.dialogId = dialogId; + load(); + } + + public boolean loading; + public boolean endReached; + public String lastOffset; + public ArrayList gifts = new ArrayList<>(); + public int currentRequestId = -1; + public int totalCount; + + public boolean shown; + + public void invalidate(boolean load) { + if (currentRequestId != -1) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(currentRequestId, true); + currentRequestId = -1; + } + loading = false; + gifts.clear(); + lastOffset = null; + endReached = false; + if (load || shown) load(); + } + + public void load() { + if (loading || endReached) return; + + boolean first = lastOffset == null; + loading = true; + TL_stars.getUserStarGifts req = new TL_stars.getUserStarGifts(); + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(dialogId); + req.offset = first ? "" : lastOffset; + req.limit = first ? 15 : 30; + final int[] reqId = new int[1]; + reqId[0] = currentRequestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (reqId[0] != currentRequestId) return; + loading = false; + currentRequestId = -1; + if (res instanceof TL_stars.TL_userStarGifts) { + TL_stars.TL_userStarGifts rez = (TL_stars.TL_userStarGifts) res; + MessagesController.getInstance(currentAccount).putUsers(rez.users, false); + + if (first) { + gifts.clear(); + } + gifts.addAll(rez.gifts); + lastOffset = rez.next_offset; + totalCount = rez.count; + endReached = gifts.size() > totalCount || lastOffset == null; + } else { + endReached = true; + } + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.starUserGiftsLoaded, dialogId, GiftsList.this); + })); + } + } + + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsIntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsIntroActivity.java index 7e2f4dd805..ec6eff33d7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsIntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stars/StarsIntroActivity.java @@ -1,6 +1,7 @@ package org.telegram.ui.Stars; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.translitSafe; import static org.telegram.messenger.LocaleController.formatPluralString; import static org.telegram.messenger.LocaleController.formatPluralStringComma; import static org.telegram.messenger.LocaleController.formatPluralStringSpaced; @@ -43,6 +44,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.TableRow; import android.widget.TextView; import androidx.annotation.NonNull; @@ -56,6 +58,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BillingController; import org.telegram.messenger.BirthdayController; import org.telegram.messenger.ChatObject; @@ -80,8 +83,10 @@ import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stars; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; @@ -97,6 +102,7 @@ import org.telegram.ui.Components.BottomSheetWithRecyclerListView; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.ButtonSpan; import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -123,6 +129,7 @@ import org.telegram.ui.Components.UniversalRecyclerView; import org.telegram.ui.Components.ViewPagerFixed; import org.telegram.ui.Components.spoilers.SpoilerEffect2; +import org.telegram.ui.Gifts.GiftSheet; import org.telegram.ui.GradientHeaderActivity; import org.telegram.ui.ImageReceiverSpan; import org.telegram.ui.LaunchActivity; @@ -148,6 +155,14 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi private View emptyLayout; private FireworksOverlay fireworksOverlay; + private LinearLayout balanceLayout; + private LinearLayout starBalanceLayout; + private SpannableStringBuilder starBalanceIcon; + private AnimatedTextView starBalanceTextView; + private TextView starBalanceTitleView; + private ButtonWithCounterView buyButton; + private ButtonWithCounterView giftButton; + public StarsIntroActivity() { setWhiteBackground(true); } @@ -160,6 +175,7 @@ public boolean onFragmentCreate() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starSubscriptionsLoaded); StarsController.getInstance(currentAccount).invalidateTransactions(true); StarsController.getInstance(currentAccount).invalidateSubscriptions(true); + StarsController.getInstance(currentAccount).getOptions(); return super.onFragmentCreate(); } @@ -204,6 +220,8 @@ public void didReceivedNotification(int id, int account, Object... args) { if (adapter != null) { adapter.update(true); } + } else if (id == NotificationCenter.starBalanceUpdated) { + updateBalance(); } } @@ -238,8 +256,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.createView(context); - balanceView = new StarsBalanceView(context, currentAccount); - actionBar.addView(balanceView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM)); +// balanceView = new StarsBalanceView(context, currentAccount); +// actionBar.addView(balanceView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM)); // yOffset = dp(16); aboveTitleView = new FrameLayout(context); @@ -250,7 +268,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { iconTextureView.mRenderer.updateColors(); iconTextureView.setStarParticlesView(particlesView); aboveTitleView.addView(iconTextureView, LayoutHelper.createFrame(190, 190, Gravity.CENTER, 0, 32, 0, 24)); - configureHeader(getString("TelegramStars", R.string.TelegramStars), getString(R.string.TelegramStarsInfo), aboveTitleView, null); + configureHeader(getString(R.string.TelegramStars), AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.TelegramStarsInfo2), () -> { + new ExplainStarsSheet(context).show(); + }), true), aboveTitleView, null); listView.setOverScrollMode(View.OVER_SCROLL_NEVER); DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); @@ -269,9 +289,72 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { fireworksOverlay = new FireworksOverlay(getContext()); contentView.addView(fireworksOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + final StarsController s = StarsController.getInstance(currentAccount); + + balanceLayout = new LinearLayout(getContext()); + balanceLayout.setOrientation(LinearLayout.VERTICAL); + balanceLayout.setPadding(0, 0, 0, dp(10)); + + starBalanceTextView = new AnimatedTextView(getContext(), false, true, false); + starBalanceTextView.setTypeface(AndroidUtilities.bold()); + starBalanceTextView.setTextSize(dp(32)); + starBalanceTextView.setGravity(Gravity.CENTER); + starBalanceTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourceProvider)); + + starBalanceIcon = new SpannableStringBuilder("S"); + final ImageReceiverSpan starBalanceIconSpan = new ImageReceiverSpan(starBalanceTextView, currentAccount, 42); + starBalanceIconSpan.imageReceiver.setImageBitmap(new RLottieDrawable(R.raw.star_reaction, "s" + R.raw.star_reaction, dp(42), dp(42))); + starBalanceIconSpan.imageReceiver.setAutoRepeat(2); + starBalanceIconSpan.enableShadow(false); + starBalanceIconSpan.translate(-dp(3), 0); + starBalanceIcon.setSpan(starBalanceIconSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + balanceLayout.addView(starBalanceTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.CENTER, 24, 0, 24, 0)); + + starBalanceTitleView = new TextView(getContext()); + starBalanceTitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + starBalanceTitleView.setGravity(Gravity.CENTER); + starBalanceTitleView.setText(LocaleController.getString(R.string.YourStarsBalance)); + starBalanceTitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourceProvider)); + balanceLayout.addView(starBalanceTitleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 24, 0, 24, 0)); + + buyButton = new ButtonWithCounterView(getContext(), resourceProvider); + buyButton.setOnClickListener(v -> { + new StarsOptionsSheet(context, resourceProvider).show(); + }); + balanceLayout.addView(buyButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER, 20, 17, 20, 0)); + + giftButton = new ButtonWithCounterView(getContext(), false, resourceProvider); + SpannableStringBuilder sb2 = new SpannableStringBuilder(); + sb2.append("G "); + sb2.setSpan(new ColoredImageSpan(R.drawable.menu_stars_gift), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + sb2.append(LocaleController.getString(R.string.TelegramStarsGift)); + giftButton.setText(sb2, false); + giftButton.setOnClickListener(v -> { + StarsController.getInstance(currentAccount).getGiftOptions(); + UserSelectorBottomSheet.open(UserSelectorBottomSheet.TYPE_STARS, 0, BirthdayController.getInstance(currentAccount).getState()); + }); + balanceLayout.addView(giftButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER, 20, 8, 20, 0)); + + updateBalance(); + + if (adapter != null) { + adapter.update(false); + } + return fragmentView; } + private void updateBalance() { + final StarsController s = StarsController.getInstance(currentAccount); + + SpannableStringBuilder sb = new SpannableStringBuilder(); + sb.append(starBalanceIcon); + sb.append(LocaleController.formatNumber(s.getBalance(), ',')); + starBalanceTextView.setText(sb); + + buyButton.setText(LocaleController.getString(s.getBalance() > 0 ? R.string.StarsBuyMore : R.string.StarsBuy), true); + } + @Override protected ContentView createContentView() { return new NestedFrameLayout(getContext()); @@ -504,39 +587,46 @@ public void fillItems(ArrayList items, UniversalAdapter adapter) { final StarsController c = StarsController.getInstance(currentAccount); items.add(UItem.asFullyCustom(getHeader(getContext()))); - items.add(UItem.asAnimatedHeader(-99, getString(R.string.TelegramStarsChoose))); + items.add(UItem.asCustom(balanceLayout)); - int stars = 1; - ArrayList options = c.getOptions(); - if (options != null && !options.isEmpty()) { - int hidden = 0; - for (int id = 0; id < options.size(); ++id) { - TLRPC.TL_starsTopupOption option = options.get(id); - if (option.extended && !expanded) { - hidden++; - continue; - } - items.add(StarTierView.Factory.asStarTier(id, stars++, option)); - } - if (!expanded && hidden > 0) { - items.add(ExpandView.Factory.asExpand(BUTTON_EXPAND, getString(expanded ? R.string.NotifyLessOptions : R.string.NotifyMoreOptions), !expanded).accent()); - } - } else { - items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); - items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); - items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); - items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); - items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); + if (giftButton != null) { + giftButton.setVisibility(getMessagesController().starsGiftsEnabled ? View.VISIBLE : View.GONE); } - items.add(UItem.asShadow(AndroidUtilities.replaceSingleTag(getString(R.string.StarsTOS), () -> { - Browser.openUrl(getContext(), getString(R.string.StarsTOSLink)); - }))); - - if (getMessagesController().starsGiftsEnabled) { - items.add(UItem.asButton(BUTTON_GIFT, R.drawable.menu_stars_gift, getString(R.string.TelegramStarsGift)).accent()); - items.add(UItem.asShadow(null)); - } +// items.add(UItem.asAnimatedHeader(-99, getString(R.string.TelegramStarsChoose))); +// +// int stars = 1; +// ArrayList options = c.getOptions(); +// if (options != null && !options.isEmpty()) { +// int hidden = 0; +// for (int id = 0; id < options.size(); ++id) { +// TL_stars.TL_starsTopupOption option = options.get(id); +// if (option.extended && !expanded) { +// hidden++; +// continue; +// } +// items.add(StarTierView.Factory.asStarTier(id, stars++, option)); +// } +// if (!expanded && hidden > 0) { +// items.add(ExpandView.Factory.asExpand(BUTTON_EXPAND, getString(expanded ? R.string.NotifyLessOptions : R.string.NotifyMoreOptions), !expanded).accent()); +// } +// } else { +// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); +// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); +// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); +// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); +// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); +// } +// +// items.add(UItem.asShadow(AndroidUtilities.replaceSingleTag(getString(R.string.StarsTOS), () -> { +// Browser.openUrl(getContext(), getString(R.string.StarsTOSLink)); +// }))); + items.add(UItem.asShadow(null)); +// +// if (getMessagesController().starsGiftsEnabled) { +// items.add(UItem.asButton(BUTTON_GIFT, R.drawable.menu_stars_gift, getString(R.string.TelegramStarsGift)).accent()); +// items.add(UItem.asShadow(null)); +// } if (c.hasSubscriptions()) { items.add(UItem.asHeader(getString(R.string.StarMySubscriptions))); @@ -569,8 +659,8 @@ public void onItemClick(UItem item, int position) { StarsController.getInstance(currentAccount).loadSubscriptions(); adapter.update(true); } else if (item.instanceOf(StarTierView.Factory.class)) { - if (item.object instanceof TLRPC.TL_starsTopupOption) { - StarsController.getInstance(currentAccount).buy(getParentActivity(), (TLRPC.TL_starsTopupOption) item.object, (success, error) -> { + if (item.object instanceof TL_stars.TL_starsTopupOption) { + StarsController.getInstance(currentAccount).buy(getParentActivity(), (TL_stars.TL_starsTopupOption) item.object, (success, error) -> { if (getContext() == null) return; if (success) { BulletinFactory.of(this).createSimpleBulletin(R.raw.stars_topup, getString(R.string.StarsAcquired), AndroidUtilities.replaceTags(formatPluralString("StarsAcquiredInfo", (int) item.longValue))).show(); @@ -582,8 +672,8 @@ public void onItemClick(UItem item, int position) { }); } } else if (item.instanceOf(StarsSubscriptionView.Factory.class)) { - if (item.object instanceof TLRPC.StarsSubscription) { - showSubscriptionSheet(getContext(), currentAccount, (TLRPC.StarsSubscription) item.object, getResourceProvider()); + if (item.object instanceof TL_stars.StarsSubscription) { + showSubscriptionSheet(getContext(), currentAccount, (TL_stars.StarsSubscription) item.object, getResourceProvider()); } } } @@ -814,7 +904,7 @@ public void bindView(View view, UItem item, boolean divider) { ((StarTierView) view).set(item.intValue, item.text, item.subtext, divider); } - public static UItem asStarTier(int id, int index, TLRPC.TL_starsTopupOption option) { + public static UItem asStarTier(int id, int index, TL_stars.TL_starsTopupOption option) { UItem item = UItem.ofFactory(StarTierView.Factory.class); item.id = id; item.intValue = index; @@ -825,7 +915,7 @@ public static UItem asStarTier(int id, int index, TLRPC.TL_starsTopupOption opti return item; } - public static UItem asStarTier(int id, int index, TLRPC.TL_starsGiftOption option) { + public static UItem asStarTier(int id, int index, TL_stars.TL_starsGiftOption option) { UItem item = UItem.ofFactory(StarTierView.Factory.class); item.id = id; item.intValue = index; @@ -1125,7 +1215,9 @@ public boolean isLoadingVisible() { public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.starTransactionsLoaded) { listView.adapter.update(true); - loadTransactionsRunnable.run(); + if (!Page.this.listView.canScrollVertically(1) || isLoadingVisible()) { + loadTransactionsRunnable.run(); + } } else if (id == NotificationCenter.botStarsTransactionsLoaded) { if ((long) args[0] == bot_id) { listView.adapter.update(true); @@ -1157,7 +1249,7 @@ protected void onDetachedFromWindow() { private void fillItems(ArrayList items, UniversalAdapter adapter) { if (bot_id != 0) { final BotStarsController c = BotStarsController.getInstance(currentAccount); - for (TLRPC.StarsTransaction t : c.getTransactions(bot_id, type)) { + for (TL_stars.StarsTransaction t : c.getTransactions(bot_id, type)) { items.add(StarsTransactionView.Factory.asTransaction(t, true)); } if (!c.didFullyLoadTransactions(bot_id, type)) { @@ -1167,7 +1259,7 @@ private void fillItems(ArrayList items, UniversalAdapter adapter) { } } else { final StarsController c = StarsController.getInstance(currentAccount); - for (TLRPC.StarsTransaction t : c.transactions[type]) { + for (TL_stars.StarsTransaction t : c.transactions[type]) { items.add(StarsTransactionView.Factory.asTransaction(t, false)); } if (!c.didFullyLoadTransactions(type)) { @@ -1179,8 +1271,8 @@ private void fillItems(ArrayList items, UniversalAdapter adapter) { } private void onClick(UItem item, View view, int position, float x, float y) { - if (item.object instanceof TLRPC.StarsTransaction) { - showTransactionSheet(getContext(), false, 0, currentAccount, (TLRPC.StarsTransaction) item.object, resourcesProvider); + if (item.object instanceof TL_stars.StarsTransaction) { + showTransactionSheet(getContext(), false, 0, currentAccount, (TL_stars.StarsTransaction) item.object, resourcesProvider); } } @@ -1318,10 +1410,10 @@ public static CombinedDrawable getPlatformDrawable(String platform, int sz) { private Runnable cancelCurrentGift; private boolean needDivider; - public void set(TLRPC.StarsTransaction transaction, boolean bot, boolean divider) { + public void set(TL_stars.StarsTransaction transaction, boolean bot, boolean divider) { long did = DialogObject.getPeerDialogId(transaction.peer.peer); - threeLines = did != 0 || transaction.subscription || transaction.gift && transaction.peer instanceof TLRPC.TL_starsTransactionPeerFragment; + threeLines = did != 0 || transaction.subscription || transaction.stargift != null || transaction.gift && transaction.peer instanceof TL_stars.TL_starsTransactionPeerFragment; titleTextViewParams.bottomMargin = threeLines ? 0 : dp(4.33f); subtitleTextView.setVisibility(threeLines ? View.VISIBLE : View.GONE); dateTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, threeLines ? 13 : 14); @@ -1344,7 +1436,15 @@ public void set(TLRPC.StarsTransaction transaction, boolean bot, boolean divider imageView.setTranslationY(0); imageView2.setVisibility(GONE); imageView.setRoundRadius(dp(46)); - if (did != 0) { + if (transaction.stargift != null) { + setGiftImage(imageView.getImageReceiver(), transaction.stargift, 46); + titleTextView.setText(MessagesController.getInstance(currentAccount).getPeerName(DialogObject.getPeerDialogId(transaction.peer.peer))); + if (transaction.refund) { + subtitleTextView.setText(LocaleController.getString(transaction.stars > 0 ? R.string.Gift2TransactionRefundedSent : R.string.Gift2TransactionRefundedConverted)); + } else { + subtitleTextView.setText(LocaleController.getString(transaction.stars > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent)); + } + } else if (did != 0) { boolean deleted = false; String username; if (UserObject.isService(did)) { @@ -1430,13 +1530,13 @@ public void set(TLRPC.StarsTransaction transaction, boolean bot, boolean divider subtitleTextView.setVisibility(deleted ? GONE : VISIBLE); subtitleTextView.setText(username); } - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerAppStore) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerAppStore) { titleTextView.setText(getString(R.string.StarsTransactionInApp)); imageView.setImageDrawable(getPlatformDrawable("ios")); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerPlayMarket) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerPlayMarket) { titleTextView.setText(getString(R.string.StarsTransactionInApp)); imageView.setImageDrawable(getPlatformDrawable("android")); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerFragment) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerFragment) { if (transaction.gift) { titleTextView.setText(LocaleController.getString(R.string.StarsGiftReceived)); subtitleTextView.setText(getString(R.string.StarsTransactionUnknown)); @@ -1445,13 +1545,13 @@ public void set(TLRPC.StarsTransaction transaction, boolean bot, boolean divider titleTextView.setText(getString(bot ? R.string.StarsTransactionWithdrawFragment : R.string.StarsTransactionFragment)); } imageView.setImageDrawable(getPlatformDrawable("fragment")); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerPremiumBot) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerPremiumBot) { titleTextView.setText(getString(R.string.StarsTransactionBot)); imageView.setImageDrawable(getPlatformDrawable("premiumbot")); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerUnsupported) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerUnsupported) { titleTextView.setText(getString(R.string.StarsTransactionUnsupported)); imageView.setImageDrawable(getPlatformDrawable("?")); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerAds) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerAds) { titleTextView.setText(getString(R.string.StarsTransactionAds)); imageView.setImageDrawable(getPlatformDrawable("ads")); } else { @@ -1509,10 +1609,10 @@ public StarsTransactionView createView(Context context, int currentAccount, int @Override public void bindView(View view, UItem item, boolean divider) { StarsTransactionView transactionView = (StarsTransactionView) view; - transactionView.set((TLRPC.StarsTransaction) item.object, item.accent, divider); + transactionView.set((TL_stars.StarsTransaction) item.object, item.accent, divider); } - public static UItem asTransaction(TLRPC.StarsTransaction transaction, boolean bot) { + public static UItem asTransaction(TL_stars.StarsTransaction transaction, boolean bot) { UItem item = UItem.ofFactory(StarsTransactionView.Factory.class); item.object = transaction; item.accent = bot; @@ -1586,7 +1686,7 @@ public StarsSubscriptionView(Context context, int currentAccount, Theme.Resource priceLayout.addView(priceSubtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT, 0, 0, 0, 0)); } - public void set(TLRPC.StarsSubscription subscription, boolean divider) { + public void set(TL_stars.StarsSubscription subscription, boolean divider) { long dialogId = DialogObject.getPeerDialogId(subscription.peer); TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); @@ -1656,10 +1756,10 @@ public StarsSubscriptionView createView(Context context, int currentAccount, int @Override public void bindView(View view, UItem item, boolean divider) { StarsSubscriptionView subscriptionView = (StarsSubscriptionView) view; - subscriptionView.set((TLRPC.StarsSubscription) item.object, divider); + subscriptionView.set((TL_stars.StarsSubscription) item.object, divider); } - public static UItem asSubscription(TLRPC.StarsSubscription subscription) { + public static UItem asSubscription(TL_stars.StarsSubscription subscription) { UItem item = UItem.ofFactory(StarsSubscriptionView.Factory.class); item.object = subscription; return item; @@ -1669,9 +1769,9 @@ public static UItem asSubscription(TLRPC.StarsSubscription subscription) { public boolean equals(UItem a, UItem b) { if (a == null && b == null) return true; if (a == null || b == null) return false; - if (!(a.object instanceof TLRPC.StarsSubscription) || !(b.object instanceof TLRPC.StarsSubscription)) return false; - TLRPC.StarsSubscription subA = (TLRPC.StarsSubscription) a.object; - TLRPC.StarsSubscription subB = (TLRPC.StarsSubscription) b.object; + if (!(a.object instanceof TL_stars.StarsSubscription) || !(b.object instanceof TL_stars.StarsSubscription)) return false; + TL_stars.StarsSubscription subA = (TL_stars.StarsSubscription) a.object; + TL_stars.StarsSubscription subB = (TL_stars.StarsSubscription) b.object; return TextUtils.equals(subA.id, subB.id); } } @@ -2036,6 +2136,165 @@ public static BottomSheet openStarsChannelInviteSheet( return sheet; } + public static class StarsOptionsSheet extends BottomSheetWithRecyclerListView implements NotificationCenter.NotificationCenterDelegate { + + private final FrameLayout footerView; + private final FireworksOverlay fireworksOverlay; + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.starOptionsLoaded || id == NotificationCenter.starBalanceUpdated) { + if (adapter != null) { + adapter.update(true); + } + } + } + + @Override + public void show() { + long balance = StarsController.getInstance(currentAccount).getBalance(); + BaseFragment lastFragment = LaunchActivity.getLastFragment(); + if (lastFragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) lastFragment; + if (chatActivity.isKeyboardVisible() && chatActivity.getChatActivityEnterView() != null) { + chatActivity.getChatActivityEnterView().closeKeyboard(); + } + } + super.show(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starOptionsLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.starBalanceUpdated); + } + + @Override + public void dismissInternal() { + super.dismissInternal(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.starOptionsLoaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.starBalanceUpdated); + } + + public StarsOptionsSheet( + Context context, + Theme.ResourcesProvider resourcesProvider + ) { + super(context, null, false, false, false, resourcesProvider); + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + recyclerListView.setOnItemClickListener((view, position) -> { + if (adapter == null) return; + UItem item = adapter.getItem(position - 1); + if (item == null) return; + onItemClick(item, adapter); + }); + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDelayAnimations(false); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDurations(350); + recyclerListView.setItemAnimator(itemAnimator); + setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + fixNavigationBar(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + + actionBar.setTitle(getTitle()); + + footerView = new FrameLayout(context); + LinkSpanDrawable.LinksTextView footerTextView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + footerView.setPadding(0, dp(11), 0, dp(11)); + footerTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + footerTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4, resourcesProvider)); + footerTextView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + footerTextView.setText(AndroidUtilities.replaceSingleTag(getString(R.string.StarsTOS), () -> { + Browser.openUrl(getContext(), getString(R.string.StarsTOSLink)); + })); + footerTextView.setGravity(Gravity.CENTER); + footerTextView.setMaxWidth(HintView2.cutInFancyHalf(footerTextView.getText(), footerTextView.getPaint())); + footerView.addView(footerTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); + footerView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + + fireworksOverlay = new FireworksOverlay(getContext()); + containerView.addView(fireworksOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + if (adapter != null) { + adapter.update(false); + } + } + + @Override + protected CharSequence getTitle() { + return LocaleController.getString(R.string.StarsBuy); + } + + private UniversalAdapter adapter; + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + adapter = new UniversalAdapter(recyclerListView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider); + adapter.setApplyBackground(false); + return adapter; + } + + private boolean expanded; + private final int BUTTON_EXPAND = -1; + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + items.add(UItem.asHeader(getString(R.string.TelegramStarsChoose))); + int stars = 1; + ArrayList options = StarsController.getInstance(currentAccount).getOptions(); + if (options != null && !options.isEmpty()) { + int hidden = 0; + for (int id = 0; id < options.size(); ++id) { + TL_stars.TL_starsTopupOption option = options.get(id); + if (option.extended && !expanded) { + hidden++; + continue; + } + items.add(StarTierView.Factory.asStarTier(id, stars++, option)); + } + if (!expanded && hidden > 0) { + items.add(ExpandView.Factory.asExpand(BUTTON_EXPAND, getString(expanded ? R.string.NotifyLessOptions : R.string.NotifyMoreOptions), !expanded).accent()); + } + } else { + items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); + items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); + items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); + items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); + items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER)); + } + items.add(UItem.asCustom(footerView)); + } + + public void onItemClick(UItem item, UniversalAdapter adapter) { + if (item.id == BUTTON_EXPAND) { + expanded = !expanded; + adapter.update(true); + recyclerListView.smoothScrollBy(0, dp(300)); + } else if (item.instanceOf(StarTierView.Factory.class)) { + if (item.object instanceof TL_stars.TL_starsTopupOption) { + Activity activity = AndroidUtilities.findActivity(getContext()); + if (activity == null) { + activity = LaunchActivity.instance; + } + if (activity == null) { + return; + } + StarsController.getInstance(currentAccount).buy(activity, (TL_stars.TL_starsTopupOption) item.object, (success, error) -> { + if (getContext() == null) return; + dismiss(); + StarsController.getInstance(currentAccount).invalidateTransactions(true); + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return; + if (success) { + BulletinFactory.of(lastFragment).createSimpleBulletin(R.raw.stars_topup, getString(R.string.StarsAcquired), AndroidUtilities.replaceTags(formatPluralString("StarsAcquiredInfo", (int) item.longValue))).show(); + if (LaunchActivity.instance != null) { + LaunchActivity.instance.getFireworksOverlay().start(true); + } + } else if (error != null) { + BulletinFactory.of(lastFragment).createSimpleBulletin(R.raw.error, LocaleController.formatString(R.string.UnknownErrorCode, error)).show(); + } + }); + } + } + } + } + public static class StarsNeededSheet extends BottomSheetWithRecyclerListView implements NotificationCenter.NotificationCenterDelegate { private final long starsNeeded; @@ -2100,6 +2359,7 @@ public void dismissInternal() { public static final int TYPE_SUBSCRIPTION_REFULFIL = 3; public static final int TYPE_LINK = 4; public static final int TYPE_REACTIONS = 5; + public static final int TYPE_STAR_GIFT_BUY = 6; public StarsNeededSheet( Context context, @@ -2149,6 +2409,8 @@ public StarsNeededSheet( } } else if (type == TYPE_REACTIONS) { stringRes = "StarsNeededTextReactions"; + } else if (type == TYPE_STAR_GIFT_BUY) { + stringRes = "StarsNeededTextGift"; } else { stringRes = "StarsNeededText"; } @@ -2205,13 +2467,13 @@ public void fillItems(ArrayList items, UniversalAdapter adapter) { items.add(UItem.asCustom(headerView)); items.add(UItem.asHeader(getString(R.string.TelegramStarsChoose))); int stars = 1; - ArrayList options = StarsController.getInstance(currentAccount).getOptions(); + ArrayList options = StarsController.getInstance(currentAccount).getOptions(); if (options != null && !options.isEmpty()) { int count = 0; int hidden = 0; boolean shownNearest = false; for (int id = 0; id < options.size(); ++id) { - TLRPC.TL_starsTopupOption option = options.get(id); + TL_stars.TL_starsTopupOption option = options.get(id); if (option.stars < starsNeeded) { continue; } @@ -2229,7 +2491,7 @@ public void fillItems(ArrayList items, UniversalAdapter adapter) { items.add(UItem.asHeader(getString(R.string.TelegramStarsChoose))); count = 0; for (int id = 0; id < options.size(); ++id) { - TLRPC.TL_starsTopupOption option = options.get(id); + TL_stars.TL_starsTopupOption option = options.get(id); if (option.stars < starsNeeded) { continue; } @@ -2238,7 +2500,7 @@ public void fillItems(ArrayList items, UniversalAdapter adapter) { } if (count == 0) { for (int id = 0; id < options.size(); ++id) { - TLRPC.TL_starsTopupOption option = options.get(id); + TL_stars.TL_starsTopupOption option = options.get(id); items.add(StarTierView.Factory.asStarTier(id, stars++, option)); count++; } @@ -2269,7 +2531,7 @@ public void onItemClick(UItem item, UniversalAdapter adapter) { expanded = !expanded; adapter.update(true); } else if (item.instanceOf(StarTierView.Factory.class)) { - if (item.object instanceof TLRPC.TL_starsTopupOption) { + if (item.object instanceof TL_stars.TL_starsTopupOption) { Activity activity = AndroidUtilities.findActivity(getContext()); if (activity == null) { activity = LaunchActivity.instance; @@ -2277,7 +2539,7 @@ public void onItemClick(UItem item, UniversalAdapter adapter) { if (activity == null) { return; } - StarsController.getInstance(currentAccount).buy(activity, (TLRPC.TL_starsTopupOption) item.object, (success, error) -> { + StarsController.getInstance(currentAccount).buy(activity, (TL_stars.TL_starsTopupOption) item.object, (success, error) -> { if (getContext() == null) return; if (success) { BulletinFactory.of((FrameLayout) containerView, resourcesProvider).createSimpleBulletin(R.raw.stars_topup, getString(R.string.StarsAcquired), AndroidUtilities.replaceTags(formatPluralString("StarsAcquiredInfo", (int) item.longValue))).show(); @@ -2490,11 +2752,11 @@ public void fillItems(ArrayList items, UniversalAdapter adapter) { items.add(UItem.asCustom(headerView)); items.add(UItem.asHeader(getString(R.string.TelegramStarsChoose))); int stars = 1; - ArrayList options = StarsController.getInstance(currentAccount).getGiftOptions(); + ArrayList options = StarsController.getInstance(currentAccount).getGiftOptions(); if (options != null && !options.isEmpty()) { int hidden = 0; for (int id = 0; id < options.size(); ++id) { - TLRPC.TL_starsGiftOption option = options.get(id); + TL_stars.TL_starsGiftOption option = options.get(id); if (!expanded && option.extended) { hidden++; continue; @@ -2518,7 +2780,7 @@ public void onItemClick(UItem item, UniversalAdapter adapter) { adapter.update(true); recyclerListView.smoothScrollBy(0, dp(200), CubicBezierInterpolator.EASE_OUT); } else if (item.instanceOf(StarTierView.Factory.class)) { - if (item.object instanceof TLRPC.TL_starsGiftOption) { + if (item.object instanceof TL_stars.TL_starsGiftOption) { Activity activity = AndroidUtilities.findActivity(getContext()); if (activity == null) { activity = LaunchActivity.instance; @@ -2527,7 +2789,7 @@ public void onItemClick(UItem item, UniversalAdapter adapter) { return; } final long userId = user.id; - StarsController.getInstance(currentAccount).buyGift(activity, (TLRPC.TL_starsGiftOption) item.object, userId, (success, error) -> { + StarsController.getInstance(currentAccount).buyGift(activity, (TL_stars.TL_starsGiftOption) item.object, userId, (success, error) -> { if (getContext() == null) return; if ((success || error != null) && whenPurchased != null) { whenPurchased.run(); @@ -2686,10 +2948,17 @@ public static SpannableStringBuilder replaceStarsWithPlain(CharSequence cs, floa return ssb; } - public static CharSequence getTransactionTitle(int currentAccount, boolean bot, TLRPC.StarsTransaction t) { + public static CharSequence getTransactionTitle(int currentAccount, boolean bot, TL_stars.StarsTransaction t) { if (!t.extended_media.isEmpty()) { return getString(R.string.StarMediaPurchase); } + if (t.stargift != null) { + if (t.refund) { + return LocaleController.getString(t.stars > 0 ? R.string.Gift2TransactionRefundedSent : R.string.Gift2TransactionRefundedConverted); + } else { + return LocaleController.getString(t.stars > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent); + } + } if (t.subscription) { if (t.subscription_period == StarsController.PERIOD_MONTHLY) { return getString(R.string.StarSubscriptionPurchase); @@ -2722,9 +2991,9 @@ public static CharSequence getTransactionTitle(int currentAccount, boolean bot, TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-did); return chat == null ? "" : chat.title; } - } else if (t.peer instanceof TLRPC.TL_starsTransactionPeerFragment) { + } else if (t.peer instanceof TL_stars.TL_starsTransactionPeerFragment) { return getString(bot ? R.string.StarsTransactionWithdrawFragment : R.string.StarsTransactionFragment); - } else if (t.peer instanceof TLRPC.TL_starsTransactionPeerPremiumBot) { + } else if (t.peer instanceof TL_stars.TL_starsTransactionPeerPremiumBot) { return getString(R.string.StarsTransactionBot); } else { return getString(R.string.StarsTransactionUnsupported); @@ -2732,11 +3001,11 @@ public static CharSequence getTransactionTitle(int currentAccount, boolean bot, } public static BottomSheet showTransactionSheet(Context context, int currentAccount, int date, TLRPC.Peer sent_by, TLRPC.Peer received_by, TLRPC.TL_messageActionPrizeStars action, Theme.ResourcesProvider resourcesProvider) { - TLRPC.StarsTransaction t = new TLRPC.StarsTransaction(); + TL_stars.StarsTransaction t = new TL_stars.StarsTransaction(); t.title = null; t.description = null; t.photo = null; - t.peer = new TLRPC.TL_starsTransactionPeer(); + t.peer = new TL_stars.TL_starsTransactionPeer(); t.peer.peer = action.boost_peer; t.date = date; t.stars = action.stars; @@ -2750,11 +3019,11 @@ public static BottomSheet showTransactionSheet(Context context, int currentAccou } public static BottomSheet showTransactionSheet(Context context, int currentAccount, int date, TLRPC.Peer sent_by, TLRPC.Peer received_by, TLRPC.TL_messageActionGiftStars action, Theme.ResourcesProvider resourcesProvider) { - TLRPC.StarsTransaction t = new TLRPC.StarsTransaction(); + TL_stars.StarsTransaction t = new TL_stars.StarsTransaction(); t.title = null; t.description = null; t.photo = null; - t.peer = new TLRPC.TL_starsTransactionPeer(); + t.peer = new TL_stars.TL_starsTransactionPeer(); t.peer.peer = sent_by; t.date = date; t.stars = action.stars; @@ -2766,11 +3035,11 @@ public static BottomSheet showTransactionSheet(Context context, int currentAccou } public static BottomSheet showTransactionSheet(Context context, int currentAccount, int date, TLRPC.TL_messageActionPaymentRefunded action, Theme.ResourcesProvider resourcesProvider) { - TLRPC.StarsTransaction t = new TLRPC.StarsTransaction(); + TL_stars.StarsTransaction t = new TL_stars.StarsTransaction(); t.title = null; t.description = null; t.photo = null; - t.peer = new TLRPC.TL_starsTransactionPeer(); + t.peer = new TL_stars.TL_starsTransactionPeer(); t.peer.peer = action.peer; t.date = date; t.stars = action.total_amount; @@ -2780,11 +3049,11 @@ public static BottomSheet showTransactionSheet(Context context, int currentAccou } public static BottomSheet showTransactionSheet(Context context, boolean bot, int currentAccount, TLRPC.TL_payments_paymentReceiptStars receipt, Theme.ResourcesProvider resourcesProvider) { - TLRPC.StarsTransaction t = new TLRPC.StarsTransaction(); + TL_stars.StarsTransaction t = new TL_stars.StarsTransaction(); t.title = receipt.title; t.description = receipt.description; t.photo = receipt.photo; - t.peer = new TLRPC.TL_starsTransactionPeer(); + t.peer = new TL_stars.TL_starsTransactionPeer(); t.peer.peer = MessagesController.getInstance(currentAccount).getPeer(receipt.bot_id); t.date = receipt.date; t.stars = -receipt.total_amount; @@ -2793,6 +3062,18 @@ public static BottomSheet showTransactionSheet(Context context, boolean bot, int } public static Runnable setGiftImage(View view, ImageReceiver imageReceiver, long stars) { + int type; + if (stars <= 1_000) { + type = 2; + } else if (stars < 2_500) { + type = 3; + } else { + type = 4; + } + return setGiftImage(view, imageReceiver, type); + } + + public static Runnable setGiftImage(View view, ImageReceiver imageReceiver, int type) { final boolean[] played = new boolean[1]; final int currentAccount = imageReceiver.getCurrentAccount(); Runnable setImage = () -> { @@ -2810,9 +3091,9 @@ public static Runnable setGiftImage(View view, ImageReceiver imageReceiver, long } if (set != null) { String emoji; - if (stars <= 1000) { + if (type == 2) { emoji = "2⃣"; - } else if (stars < 2500) { + } else if (type == 3) { emoji = "3⃣"; } else { emoji = "4⃣"; @@ -2852,8 +3133,16 @@ public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb, } }); SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.3f); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 160, true, null, true); imageReceiver.setAutoRepeat(0); - imageReceiver.setImage(ImageLocation.getForDocument(document), String.format(Locale.US, "%d_%d_nr", 160, 160), svgThumb, "tgs", set, 1); + imageReceiver.setImage( + ImageLocation.getForDocument(document), "160_160_nr", + ImageLocation.getForDocument(thumb, document), "160_160", + svgThumb, + document.size, "tgs", + set, + 1 + ); } else { MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, set == null); } @@ -2867,7 +3156,7 @@ public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb, }; } - public static BottomSheet showTransactionSheet(Context context, boolean bot, long dialogId, int currentAccount, TLRPC.StarsTransaction transaction, Theme.ResourcesProvider resourcesProvider) { + public static BottomSheet showTransactionSheet(Context context, boolean bot, long dialogId, int currentAccount, TL_stars.StarsTransaction transaction, Theme.ResourcesProvider resourcesProvider) { if (transaction == null || context == null) return null; @@ -2883,7 +3172,10 @@ public static BottomSheet showTransactionSheet(Context context, boolean bot, lon linearLayout.setClipToPadding(false); BackupImageView imageView = new BackupImageView(context); - if (giveaway || transaction.gift) { + if (transaction.stargift != null) { + setGiftImage(imageView.getImageReceiver(), transaction.stargift, 160); + linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10)); + } else if (giveaway || transaction.gift) { setGiftImage(imageView, imageView.getImageReceiver(), transaction.stars); linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10)); } else if (!transaction.extended_media.isEmpty()) { @@ -2954,7 +3246,7 @@ public boolean validateGroupId(long groupId) { } }); }); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeer) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeer) { if (transaction.photo != null) { imageView.setRoundRadius(dp(50)); imageView.setImage(ImageLocation.getForWebFile(WebFile.createWithWebDocument(transaction.photo)), "100_100", null, 0, null); @@ -2975,15 +3267,15 @@ public boolean validateGroupId(long groupId) { linearLayout.addView(imageView, LayoutHelper.createLinear(100, 100, Gravity.CENTER, 0, 0, 0, 10)); } else { String platform = "?"; - if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerAppStore) { + if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerAppStore) { platform = "ios"; - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerPlayMarket) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerPlayMarket) { platform = "android"; - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerPremiumBot) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerPremiumBot) { platform = "premiumbot"; - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerFragment) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerFragment) { platform = "fragment"; - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerAds) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerAds) { platform = "ads"; } CombinedDrawable drawable = (CombinedDrawable) SessionCell.createDrawable(100, platform); @@ -3057,7 +3349,59 @@ public boolean validateGroupId(long groupId) { } TableView tableView = new TableView(context, resourcesProvider); - if (transaction.peer instanceof TLRPC.TL_starsTransactionPeer) { + if (transaction.stargift != null) { + if (!transaction.refund) { + // final boolean out = t.stars > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent + final long did = DialogObject.getPeerDialogId(transaction.peer.peer); + if (transaction.stars > 0) { // converted + tableView.addRowUser(getString(R.string.StarGiveawayPrizeFrom), currentAccount, did, () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + if ((transaction.flags & 8192) != 0) { + lastFragment.presentFragment(ChatActivity.of(did, transaction.giveaway_post_id)); + } else { + lastFragment.presentFragment(ChatActivity.of(did)); + } + } + }); + tableView.addRowUser(getString(R.string.StarGiveawayPrizeTo), currentAccount, UserConfig.getInstance(currentAccount).getClientUserId(), () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + final Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + lastFragment.presentFragment(new ProfileActivity(args)); + } + }); + } else { // sent + tableView.addRowUser(getString(R.string.StarGiveawayPrizeFrom), currentAccount, UserConfig.getInstance(currentAccount).getClientUserId(), () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + final Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + lastFragment.presentFragment(new ProfileActivity(args)); + } + }); + tableView.addRowUser(getString(R.string.StarGiveawayPrizeTo), currentAccount, did, () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + if ((transaction.flags & 8192) != 0) { + lastFragment.presentFragment(ChatActivity.of(did, transaction.giveaway_post_id)); + } else { + lastFragment.presentFragment(ChatActivity.of(did)); + } + } + }); + } + } + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeer) { final long did = DialogObject.getPeerDialogId(transaction.peer.peer); if (giveaway) { tableView.addRowUser(getString(R.string.StarGiveawayPrizeFrom), currentAccount, did, () -> { @@ -3118,7 +3462,7 @@ public boolean validateGroupId(long groupId) { } }); } - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerFragment) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerFragment) { if (transaction.gift) { textView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); textView.setPadding(dp(12.66f), dp(9.33f), dp(12.66f), dp(9.33f)); @@ -3152,15 +3496,15 @@ public void updateDrawState(@NonNull TextPaint ds) { } else { tableView.addRow(getString(R.string.StarsTransactionSource), getString(R.string.Fragment)); } - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerAppStore) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerAppStore) { tableView.addRow(getString(R.string.StarsTransactionSource), getString(R.string.AppStore)); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerPlayMarket) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerPlayMarket) { tableView.addRow(getString(R.string.StarsTransactionSource), getString(R.string.PlayMarket)); - } else if (transaction.peer instanceof TLRPC.TL_starsTransactionPeerPremiumBot) { + } else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeerPremiumBot) { tableView.addRow(getString(R.string.StarsTransactionSource), getString(R.string.StarsTransactionBot)); } - if (transaction.peer instanceof TLRPC.TL_starsTransactionPeer && (transaction.flags & 256) != 0) { + if (transaction.peer instanceof TL_stars.TL_starsTransactionPeer && (transaction.flags & 256) != 0) { long did = DialogObject.getPeerDialogId(transaction.peer.peer); if (bot) { did = dialogId; @@ -3240,12 +3584,12 @@ public void updateDrawState(@NonNull TextPaint ds) { idLayout.setPadding(dp(12.66f), dp(9.33f), dp(10.66f), dp(9.33f)); textView = new TextView(context); textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MONO)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 9); textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); textView.setMaxLines(4); textView.setSingleLine(false); textView.setText(transaction.id); - idLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 32, 0)); + idLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 34, 0)); ImageView copyView = new ImageView(context); copyView.setImageResource(R.drawable.msg_copy); copyView.setScaleType(ImageView.ScaleType.CENTER); @@ -3262,6 +3606,15 @@ public void updateDrawState(@NonNull TextPaint ds) { } tableView.addRow(getString(R.string.StarsTransactionDate), LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterGiveawayCard().format(new Date(transaction.date * 1000L)), LocaleController.getInstance().getFormatterDay().format(new Date(transaction.date * 1000L)))); + if (transaction.stargift != null) { + if (transaction.stargift.limited) { + addAvailabilityRow(tableView, currentAccount, transaction.stargift, resourcesProvider); + } + if (!TextUtils.isEmpty(transaction.description)) { + CharSequence message = new SpannableStringBuilder(transaction.description); + tableView.addFullRow(message); + } + } linearLayout.addView(tableView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 17, 0, 0)); if ((transaction.flags & 32) != 0) { @@ -3308,7 +3661,7 @@ public void updateDrawState(@NonNull TextPaint ds) { return sheet[0]; } - public static BottomSheet showSubscriptionSheet(Context context, int currentAccount, TLRPC.StarsSubscription subscription, Theme.ResourcesProvider resourcesProvider) { + public static BottomSheet showSubscriptionSheet(Context context, int currentAccount, TL_stars.StarsSubscription subscription, Theme.ResourcesProvider resourcesProvider) { if (subscription == null || context == null) return null; @@ -3456,7 +3809,7 @@ public void updateDrawState(@NonNull TextPaint ds) { StarsController c = StarsController.getInstance(currentAccount); final Runnable refulfil = () -> { button.setLoading(true); - TLRPC.TL_fulfillStarsSubscription req = new TLRPC.TL_fulfillStarsSubscription(); + TL_stars.TL_fulfillStarsSubscription req = new TL_stars.TL_fulfillStarsSubscription(); req.subscription_id = subscription.id; req.peer = new TLRPC.TL_inputPeerSelf(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { @@ -3495,7 +3848,7 @@ public void updateDrawState(@NonNull TextPaint ds) { button.setOnClickListener(v -> { if (button.isLoading()) return; button.setLoading(true); - TLRPC.TL_changeStarsSubscription req = new TLRPC.TL_changeStarsSubscription(); + TL_stars.TL_changeStarsSubscription req = new TL_stars.TL_changeStarsSubscription(); req.canceled = false; req.peer = new TLRPC.TL_inputPeerSelf(); req.subscription_id = subscription.id; @@ -3531,7 +3884,7 @@ public void updateDrawState(@NonNull TextPaint ds) { button.setOnClickListener(v -> { if (button.isLoading()) return; button.setLoading(true); - TLRPC.TL_changeStarsSubscription req = new TLRPC.TL_changeStarsSubscription(); + TL_stars.TL_changeStarsSubscription req = new TL_stars.TL_changeStarsSubscription(); req.canceled = true; req.peer = new TLRPC.TL_inputPeerSelf(); req.subscription_id = subscription.id; @@ -3943,4 +4296,631 @@ public void afterTextChanged(Editable s) { return sheet[0]; } + public static void setGiftImage(ImageReceiver imageReceiver, TL_stars.StarGift gift, int size) { + if (gift == null || gift.sticker == null) { + imageReceiver.clearImage(); + return; + } + + final TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(gift.sticker.thumbs, size); + final SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(gift.sticker.thumbs, Theme.key_windowBackgroundGray, 0.35f); + imageReceiver.setImage( + ImageLocation.getForDocument(gift.sticker), + size + "_" + size, + ImageLocation.getForDocument(photoSize, gift.sticker), + size + "_" + size, + svgThumb, + 0, + null, + gift, + 0 + ); + } + public static BottomSheet showActionGiftSheet(Context context, int currentAccount, long dialogId, boolean out, int date, int msg_id, TLRPC.TL_messageActionStarGift action, Theme.ResourcesProvider resourcesProvider) { + if (action == null || context == null) + return null; + + final TL_stars.StarGift gift = action.gift; + if (gift == null) + return null; + + BottomSheet.Builder b = new BottomSheet.Builder(context, false, resourcesProvider); + BottomSheet[] sheet = new BottomSheet[1]; + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(dp(16), dp(20), dp(16), dp(8)); + linearLayout.setClipChildren(false); + linearLayout.setClipToPadding(false); + + BackupImageView imageView = new BackupImageView(context); + setGiftImage(imageView.getImageReceiver(), gift, 160); + linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10)); + + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setTypeface(AndroidUtilities.bold()); + textView.setGravity(Gravity.CENTER); + textView.setText(getString(out ? R.string.Gift2TitleSent : R.string.Gift2TitleReceived)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 4)); + + final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + + textView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setGravity(Gravity.CENTER); + textView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + textView.setLineSpacing(dp(2), 1f); + ((LinkSpanDrawable.LinksTextView) textView).setDisablePaddingsOffsetY(true); + final int within = MessagesController.getInstance(currentAccount).stargiftsConvertPeriodMax - (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - date); + final int withinDays = Math.max(1, within / (60 * 60 * 24)); + textView.setText(TextUtils.concat( + AndroidUtilities.replaceTags(out ? + action.saved && !action.converted ? formatString(R.string.Gift2InfoOutPinned, UserObject.getForcedFirstName(user)) : formatPluralStringComma(action.converted ? "Gift2InfoOutConverted" : "Gift2InfoOut", (int) action.convert_stars, UserObject.getForcedFirstName(user)) : + action.converted ? formatPluralStringComma("Gift2InfoConverted", (int) action.convert_stars) : formatPluralStringComma("Gift2Info", (int) action.convert_stars) + ), + " ", + AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.Gift2More).replace(' ', ' '), () -> { + new ExplainStarsSheet(context).show(); + }), true) + )); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 5, 5, 5, 4)); + + TableView tableView = new TableView(context, resourcesProvider); + final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); + final long fromId = out ? selfId : dialogId; + final long toId = out ? dialogId : selfId; + if (fromId != selfId) { + tableView.addRowUser(getString(R.string.Gift2From), currentAccount, fromId, () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + if (UserObject.isService(fromId)) return; + Bundle args = new Bundle(); + if (fromId > 0) { + args.putLong("user_id", fromId); + if (fromId == selfId) { + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + } + } else { + args.putLong("chat_id", -fromId); + } + lastFragment.presentFragment(new ProfileActivity(args)); + } + }, getString(R.string.Gift2ButtonSendGift), () -> { + new GiftSheet(context, currentAccount, fromId, sheet[0]::dismiss).show(); + }); + } + if (toId != selfId) { + tableView.addRowUser(getString(R.string.Gift2To), currentAccount, toId, () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + if (UserObject.isService(toId)) return; + Bundle args = new Bundle(); + if (toId > 0) { + args.putLong("user_id", toId); + if (toId == selfId) { + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + } + } else { + args.putLong("chat_id", -toId); + } + lastFragment.presentFragment(new ProfileActivity(args)); + } + }, getString(R.string.Gift2ButtonSendGift), () -> { + new GiftSheet(context, currentAccount, toId, sheet[0]::dismiss).show(); + }); + } + Runnable convert = null; + if (!out && !action.converted && within > 0) { + convert = () -> { + new AlertDialog.Builder(context, resourcesProvider) + .setTitle(getString(R.string.Gift2ConvertTitle)) + .setMessage(AndroidUtilities.replaceTags(formatPluralString("Gift2ConvertText2", withinDays, UserObject.getForcedFirstName(user), formatPluralStringComma("Gift2ConvertStars", (int) action.convert_stars)))) + .setPositiveButton(getString(R.string.Gift2ConvertButton), (di, w) -> { + final AlertDialog progressDialog = new AlertDialog(ApplicationLoader.applicationContext, AlertDialog.ALERT_TYPE_SPINNER); + progressDialog.showDelayed(500); + TL_stars.convertStarGift req = new TL_stars.convertStarGift(); + req.msg_id = msg_id; + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(dialogId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + progressDialog.dismissUnless(400); + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return; + if (res instanceof TLRPC.TL_boolTrue) { + sheet[0].dismiss(); + StarsController.getInstance(currentAccount).invalidateProfileGifts(dialogId); + final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(selfId); + if (userFull != null) { + userFull.stargifts_count = Math.max(0, userFull.stargifts_count - 1); + if (userFull.stargifts_count <= 0) { + userFull.flags2 &=~ 256; + } + } + StarsController.getInstance(currentAccount).invalidateBalance(); + StarsController.getInstance(currentAccount).invalidateTransactions(true); + if (!(lastFragment instanceof StarsIntroActivity)) { + final StarsIntroActivity fragment = new StarsIntroActivity(); + fragment.whenFullyVisible(() -> { + BulletinFactory.of(fragment) + .createSimpleBulletin( + R.raw.stars_topup, + LocaleController.getString(R.string.Gift2ConvertedTitle), + LocaleController.formatPluralStringComma("Gift2Converted", (int) action.convert_stars) + ) + .show(true); + }); + lastFragment.presentFragment(fragment); + } else { + BulletinFactory.of(lastFragment) + .createSimpleBulletin( + R.raw.stars_topup, + LocaleController.getString(R.string.Gift2ConvertedTitle), + LocaleController.formatPluralStringComma("Gift2Converted", (int) action.convert_stars) + ) + .show(true); + } + } else if (err != null) { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(formatString(R.string.UnknownErrorCode, err.text)).show(false); + } else { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(getString(R.string.UnknownError)).show(false); + } + })); + }) + .setNegativeButton(getString(R.string.Cancel), null) + .show(); + }; + } + tableView.addRow(getString(R.string.Gift2Value), TextUtils.concat(replaceStarsWithPlain("⭐️ " + LocaleController.formatNumber(gift.stars, ','), .8f), " ", convert == null ? "" : ButtonSpan.make(formatPluralStringComma("Gift2ButtonSell", (int) action.convert_stars), convert, resourcesProvider))); + + tableView.addRowDateTime(getString(R.string.StarsTransactionDate), date); + if (gift.limited) { + addAvailabilityRow(tableView, currentAccount, gift, resourcesProvider); + } + if (action.message != null && !TextUtils.isEmpty(action.message.text)) { + tableView.addFullRow(action.message.text, action.message.entities); + } + linearLayout.addView(tableView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 17, 0, 12)); + + if (!out && !action.converted) { + textView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setGravity(Gravity.CENTER); + textView.setLineSpacing(dp(2), 1f); + textView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + ((LinkSpanDrawable.LinksTextView) textView).setDisablePaddingsOffsetY(true); + textView.setText(AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(action.saved ? R.string.Gift2ProfileVisible2 : R.string.Gift2ProfileInvisible), () -> { + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return; + sheet[0].dismiss(); + if (!(lastFragment instanceof ProfileActivity && ((ProfileActivity) lastFragment).myProfile)) { + final Bundle args = new Bundle(); + args.putLong("user_id", selfId); + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + lastFragment.presentFragment(new ProfileActivity(args)); + } + }), true, dp(8f / 3f), dp(.66f))); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 5, 6, 5, 16)); + } + + if (out || action.converted) { + ButtonWithCounterView button = new ButtonWithCounterView(context, resourcesProvider); + button.setText(getString(R.string.OK), false); + linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + b.setCustomView(linearLayout); + sheet[0] = b.create(); + sheet[0].useBackgroundTopPadding = false; + + button.setOnClickListener(v -> { + sheet[0].dismiss(); + }); + + sheet[0].fixNavigationBar(); + BaseFragment fragment = LaunchActivity.getSafeLastFragment(); + if (!AndroidUtilities.isTablet() && !AndroidUtilities.hasDialogOnTop(fragment)) { + sheet[0].makeAttached(fragment); + } + sheet[0].show(); + return sheet[0]; + } else { + ButtonWithCounterView button1 = new ButtonWithCounterView(context, resourcesProvider); + button1.setText(getString(action.saved ? R.string.Gift2ProfileMakeInvisible : R.string.Gift2ProfileMakeVisible), false); + linearLayout.addView(button1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 0, 0, 4)); + + button1.setOnClickListener(v -> { + if (button1.isLoading()) return; + button1.setLoading(true); + + TL_stars.saveStarGift req = new TL_stars.saveStarGift(); + final boolean unsave = req.unsave = action.saved; + req.msg_id = msg_id; + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(dialogId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return; + if (res instanceof TLRPC.TL_boolTrue) { + sheet[0].dismiss(); + StarsController.getInstance(currentAccount).invalidateProfileGifts(selfId); + BulletinFactory.of(lastFragment) + .createEmojiBulletin( + gift.sticker, + LocaleController.getString(unsave ? R.string.Gift2MadePrivateTitle : R.string.Gift2MadePublicTitle), + AndroidUtilities.replaceSingleTag(LocaleController.getString(unsave ? R.string.Gift2MadePrivate : R.string.Gift2MadePublic), lastFragment instanceof ProfileActivity ? null : () -> { + final Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + final ProfileActivity profileActivity = new ProfileActivity(args); + lastFragment.presentFragment(profileActivity); + }) + ) + .show(true); + } else if (err != null) { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(formatString(R.string.UnknownErrorCode, err.text)).show(false); + } else { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(getString(R.string.UnknownError)).show(false); + } + button1.setLoading(false); + })); + }); + + b.setCustomView(linearLayout); + sheet[0] = b.create(); + sheet[0].useBackgroundTopPadding = false; + + sheet[0].fixNavigationBar(); + BaseFragment fragment = LaunchActivity.getSafeLastFragment(); + if (!AndroidUtilities.isTablet() && !AndroidUtilities.hasDialogOnTop(fragment)) { + sheet[0].makeAttached(fragment); + } + sheet[0].show(); + return sheet[0]; + } + } + + public static BottomSheet showGiftSheet(Context context, int currentAccount, long dialogId, boolean myProfile, TL_stars.UserStarGift userGift, Theme.ResourcesProvider resourcesProvider) { + if (userGift == null || context == null) + return null; + + final TL_stars.StarGift gift = userGift.gift; + if (gift == null) + return null; + + BottomSheet.Builder b = new BottomSheet.Builder(context, false, resourcesProvider); + BottomSheet[] sheet = new BottomSheet[1]; + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(dp(16), dp(20), dp(16), dp(8)); + linearLayout.setClipChildren(false); + linearLayout.setClipToPadding(false); + + BackupImageView imageView = new BackupImageView(context); + setGiftImage(imageView.getImageReceiver(), gift, 160); + linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10)); + + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setTypeface(AndroidUtilities.bold()); + textView.setGravity(Gravity.CENTER); + textView.setText(getString(myProfile ? R.string.Gift2TitleReceived : R.string.Gift2TitleProfile)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 9)); + + textView = new TextView(context); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + textView.setTypeface(AndroidUtilities.bold()); + textView.setGravity(Gravity.CENTER); + textView.setTextColor(Theme.getColor(Theme.key_color_green, resourcesProvider)); + textView.setText(replaceStarsWithPlain(LocaleController.formatNumber((int) Math.abs(Math.max(userGift.gift.convert_stars, userGift.convert_stars)), ' ') + " ⭐️", .8f)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 4)); + + final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + + int within = 0; + if (myProfile) { + textView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setGravity(Gravity.CENTER); + textView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + textView.setLineSpacing(dp(2), 1f); + ((LinkSpanDrawable.LinksTextView) textView).setDisablePaddingsOffsetY(true); + within = MessagesController.getInstance(currentAccount).stargiftsConvertPeriodMax - (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - userGift.date); + textView.setText(TextUtils.concat( + AndroidUtilities.replaceTags(myProfile ? + within <= 0 ? formatPluralStringComma("Gift2Info2Expired", (int) userGift.convert_stars) : formatPluralStringComma("Gift2Info", (int) userGift.convert_stars) : + formatPluralStringComma("Gift2Info2Out", (int) userGift.convert_stars, UserObject.getForcedFirstName(user)) + ), + " ", + AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.Gift2More).replace(' ', ' '), () -> { + new ExplainStarsSheet(context).show(); + }), true) + )); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 5, 5, 5, 4)); + } + int withinDays = Math.max(1, within / (60 * 60 * 24)); + + TableView tableView = new TableView(context, resourcesProvider); + final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); + final long fromId = (userGift.flags & 2) != 0 && !userGift.name_hidden ? userGift.from_id : UserObject.ANONYMOUS; + final TLRPC.User fromUser = MessagesController.getInstance(currentAccount).getUser(fromId); + tableView.addRowUser(getString(R.string.Gift2From), currentAccount, fromId, () -> { + sheet[0].dismiss(); + final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment != null) { + if (UserObject.isService(fromId)) return; + if ((userGift.flags & 8) != 0) { + lastFragment.presentFragment(ChatActivity.of(fromId, userGift.msg_id)); + } else { + Bundle args = new Bundle(); + if (fromId > 0) { + args.putLong("user_id", fromId); + if (fromId == selfId) { + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + } + } else { + args.putLong("chat_id", -fromId); + } + lastFragment.presentFragment(new ProfileActivity(args)); + } + } + }, fromId != selfId && fromId != UserObject.ANONYMOUS ? getString(R.string.Gift2ButtonSendGift) : null, () -> { + new GiftSheet(context, currentAccount, fromId, sheet[0]::dismiss).show(); + }); + tableView.addRow(getString(R.string.StarsTransactionDate), LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterGiveawayCard().format(new Date(userGift.date * 1000L)), LocaleController.getInstance().getFormatterDay().format(new Date(userGift.date * 1000L)))); + Runnable convert = null; + if (myProfile && (userGift.flags & 8) != 0 && (userGift.flags & 2) != 0 && within > 0) { + convert = () -> { + new AlertDialog.Builder(context, resourcesProvider) + .setTitle(getString(R.string.Gift2ConvertTitle)) + .setMessage(AndroidUtilities.replaceTags(formatPluralString("Gift2ConvertText2", withinDays, fromUser == null || UserObject.isService(fromId) ? getString(R.string.StarsTransactionHidden) : UserObject.getForcedFirstName(fromUser), formatPluralStringComma("Gift2ConvertStars", (int) userGift.convert_stars)))) + .setPositiveButton(getString(R.string.Gift2ConvertButton), (di, w) -> { + final AlertDialog progressDialog = new AlertDialog(ApplicationLoader.applicationContext, AlertDialog.ALERT_TYPE_SPINNER); + progressDialog.showDelayed(500); + TL_stars.convertStarGift req = new TL_stars.convertStarGift(); + req.msg_id = userGift.msg_id; + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(userGift.from_id); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + progressDialog.dismissUnless(400); + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return; + if (res instanceof TLRPC.TL_boolTrue) { + sheet[0].dismiss(); + StarsController.getInstance(currentAccount).invalidateProfileGifts(dialogId); + final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(selfId); + if (userFull != null) { + userFull.stargifts_count = Math.max(0, userFull.stargifts_count - 1); + if (userFull.stargifts_count <= 0) { + userFull.flags2 &=~ 256; + } + } + StarsController.getInstance(currentAccount).invalidateBalance(); + StarsController.getInstance(currentAccount).invalidateTransactions(true); + if (!(lastFragment instanceof StarsIntroActivity)) { + final StarsIntroActivity fragment = new StarsIntroActivity(); + fragment.whenFullyVisible(() -> { + BulletinFactory.of(fragment) + .createSimpleBulletin( + R.raw.stars_topup, + LocaleController.getString(R.string.Gift2ConvertedTitle), + LocaleController.formatPluralStringComma("Gift2Converted", (int) userGift.convert_stars) + ) + .show(true); + }); + lastFragment.presentFragment(fragment); + } else { + BulletinFactory.of(lastFragment) + .createSimpleBulletin( + R.raw.stars_topup, + LocaleController.getString(R.string.Gift2ConvertedTitle), + LocaleController.formatPluralStringComma("Gift2Converted", (int) userGift.convert_stars) + ) + .show(true); + } + } else if (err != null) { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(formatString(R.string.UnknownErrorCode, err.text)).show(false); + } else { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(getString(R.string.UnknownError)).show(false); + } + })); + }) + .setNegativeButton(getString(R.string.Cancel), null) + .show(); + }; + } + tableView.addRow(getString(R.string.Gift2Value), TextUtils.concat(replaceStarsWithPlain("⭐️ " + LocaleController.formatNumber(gift.stars, ','), .8f), " ", convert == null ? "" : ButtonSpan.make(formatPluralStringComma("Gift2ButtonSell", (int) userGift.convert_stars), convert, resourcesProvider))); + if (gift.limited) { + addAvailabilityRow(tableView, currentAccount, gift, resourcesProvider); + } + if (userGift.message != null && !TextUtils.isEmpty(userGift.message.text)) { + tableView.addFullRow(userGift.message.text, userGift.message.entities); + } + linearLayout.addView(tableView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 17, 0, 12)); + + if (dialogId == UserConfig.getInstance(currentAccount).getClientUserId()) { + textView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setGravity(Gravity.CENTER); + textView.setLineSpacing(dp(2), 1f); + textView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + ((LinkSpanDrawable.LinksTextView) textView).setDisablePaddingsOffsetY(true); + textView.setText(getString(!userGift.unsaved ? R.string.Gift2ProfileVisible : R.string.Gift2ProfileInvisible)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 5, 6, 5, 16)); + } + + if (!myProfile || (userGift.flags & 8) == 0 || (userGift.flags & 2) == 0) { + ButtonWithCounterView button = new ButtonWithCounterView(context, resourcesProvider); + button.setText(getString(R.string.OK), false); + linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + b.setCustomView(linearLayout); + sheet[0] = b.create(); + sheet[0].useBackgroundTopPadding = false; + + button.setOnClickListener(v -> { + sheet[0].dismiss(); + }); + + sheet[0].fixNavigationBar(); + BaseFragment fragment = LaunchActivity.getSafeLastFragment(); + if (!AndroidUtilities.isTablet() && !AndroidUtilities.hasDialogOnTop(fragment)) { + sheet[0].makeAttached(fragment); + } + sheet[0].show(); + return sheet[0]; + } else { + ButtonWithCounterView button1 = new ButtonWithCounterView(context, resourcesProvider); + button1.setText(getString(!userGift.unsaved ? R.string.Gift2ProfileMakeInvisible : R.string.Gift2ProfileMakeVisible), false); + linearLayout.addView(button1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 0, 0, 4)); + + button1.setOnClickListener(v -> { + if (button1.isLoading()) return; + button1.setLoading(true); + + TL_stars.saveStarGift req = new TL_stars.saveStarGift(); + final boolean unsave = req.unsave = !userGift.unsaved; + req.msg_id = userGift.msg_id; + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(userGift.from_id); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); + if (lastFragment == null) return; + if (res instanceof TLRPC.TL_boolTrue) { + sheet[0].dismiss(); + StarsController.getInstance(currentAccount).invalidateProfileGifts(selfId); + BulletinFactory.of(lastFragment) + .createEmojiBulletin( + gift.sticker, + LocaleController.getString(unsave ? R.string.Gift2MadePrivateTitle : R.string.Gift2MadePublicTitle), + AndroidUtilities.replaceSingleTag(LocaleController.getString(unsave ? R.string.Gift2MadePrivate : R.string.Gift2MadePublic), lastFragment instanceof ProfileActivity ? null : () -> { + final Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putBoolean("my_profile", true); + args.putBoolean("open_gifts", true); + final ProfileActivity profileActivity = new ProfileActivity(args); + lastFragment.presentFragment(profileActivity); + }) + ) + .show(true); + } else if (err != null) { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(formatString(R.string.UnknownErrorCode, err.text)).show(false); + } else { + BulletinFactory.of(sheet[0].topBulletinContainer, resourcesProvider).createErrorBulletin(getString(R.string.UnknownError)).show(false); + } + button1.setLoading(false); + })); + }); + + b.setCustomView(linearLayout); + sheet[0] = b.create(); + sheet[0].useBackgroundTopPadding = false; + + sheet[0].fixNavigationBar(); + BaseFragment fragment = LaunchActivity.getSafeLastFragment(); + if (!AndroidUtilities.isTablet() && !AndroidUtilities.hasDialogOnTop(fragment)) { + sheet[0].makeAttached(fragment); + } + sheet[0].show(); + return sheet[0]; + } + } + + public static BottomSheet showSoldOutGiftSheet(Context context, int currentAccount, TL_stars.StarGift gift, Theme.ResourcesProvider resourcesProvider) { + if (gift == null || context == null) + return null; + + BottomSheet.Builder b = new BottomSheet.Builder(context, false, resourcesProvider); + BottomSheet[] sheet = new BottomSheet[1]; + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(dp(16), dp(20), dp(16), dp(8)); + linearLayout.setClipChildren(false); + linearLayout.setClipToPadding(false); + + BackupImageView imageView = new BackupImageView(context); + setGiftImage(imageView.getImageReceiver(), gift, 160); + linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10)); + + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + textView.setTypeface(AndroidUtilities.bold()); + textView.setGravity(Gravity.CENTER); + textView.setText(getString(R.string.Gift2SoldOutSheetTitle)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 4)); + + textView = new TextView(context); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setTypeface(AndroidUtilities.bold()); + textView.setGravity(Gravity.CENTER); + textView.setTextColor(Theme.getColor(Theme.key_text_RedBold, resourcesProvider)); + textView.setText(getString(R.string.Gift2SoldOutSheetSubtitle)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 4)); + + TableView tableView = new TableView(context, resourcesProvider); + + if (gift.first_sale_date != 0) { + tableView.addRowDateTime(getString(R.string.Gift2SoldOutSheetFirstSale), gift.first_sale_date); + } + if (gift.last_sale_date != 0) { + tableView.addRowDateTime(getString(R.string.Gift2SoldOutSheetLastSale), gift.last_sale_date); + } + tableView.addRow(getString(R.string.Gift2SoldOutSheetValue), replaceStarsWithPlain("⭐️ " + LocaleController.formatNumber(gift.stars, ','), .8f)); + if (gift.limited) { + addAvailabilityRow(tableView, currentAccount, gift, resourcesProvider); + } + linearLayout.addView(tableView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 17, 0, 12)); + + ButtonWithCounterView button = new ButtonWithCounterView(context, resourcesProvider); + button.setText(getString(R.string.OK), false); + linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + b.setCustomView(linearLayout); + sheet[0] = b.create(); + sheet[0].useBackgroundTopPadding = false; + + button.setOnClickListener(v -> { + sheet[0].dismiss(); + }); + + sheet[0].fixNavigationBar(); + BaseFragment fragment = LaunchActivity.getSafeLastFragment(); + if (!AndroidUtilities.isTablet() && !AndroidUtilities.hasDialogOnTop(fragment)) { + sheet[0].makeAttached(fragment); + } + sheet[0].show(); + return sheet[0]; + } + + public static void addAvailabilityRow(TableView tableView, int currentAccount, TL_stars.StarGift gift, Theme.ResourcesProvider resourcesProvider) { + final TableRow row = tableView.addRow(getString(R.string.Gift2Availability), ""); + final TextView rowTextView = (TextView) ((TableView.TableRowContent) row.getChildAt(1)).getChildAt(0); + final SpannableStringBuilder sb = new SpannableStringBuilder("x "); + final LoadingSpan span = new LoadingSpan(rowTextView, dp(90), 0, resourcesProvider); + span.setColors( + Theme.multAlpha(rowTextView.getPaint().getColor(), .65f), + Theme.multAlpha(rowTextView.getPaint().getColor(), .08f) + ); + sb.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + rowTextView.setText(sb, TextView.BufferType.SPANNABLE); + if (!gift.sold_out) { + StarsController.getInstance(currentAccount).getStarGift(gift.id, remoteGift -> { + if (remoteGift == null) return; + rowTextView.setText(remoteGift.availability_remains <= 0 ? formatPluralStringComma("Gift2Availability2ValueNone", remoteGift.availability_total) : formatPluralStringComma("Gift2Availability4Value", remoteGift.availability_remains, LocaleController.formatNumber(remoteGift.availability_total, ','))); + }); + } else { + rowTextView.setText(gift.availability_remains <= 0 ? formatPluralStringComma("Gift2Availability2ValueNone", gift.availability_total) : formatPluralStringComma("Gift2Availability4Value", gift.availability_remains, LocaleController.formatNumber(gift.availability_total, ','))); + } + } } 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 44f7ae10f5..64725382e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -167,6 +167,7 @@ import org.telegram.ui.PinchToZoomHelper; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.ReportBottomSheet; import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.Stories.recorder.CaptionContainerView; import org.telegram.ui.Stories.recorder.HintView2; @@ -1766,7 +1767,10 @@ public void setColorFilter(ColorFilter colorFilter) { if (!unsupported) { if (!UserObject.isService(dialogId) && !isBotsPreview()) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_report, LocaleController.getString(R.string.ReportChat), false, resourcesProvider).setOnClickListener(v -> { - AlertsCreator.createReportAlert(getContext(), dialogId, 0, currentStory.storyItem.id, storyViewer.fragment, resourcesProvider, null); + if (storyViewer != null) storyViewer.setOverlayVisible(true); + ReportBottomSheet.openStory(currentAccount, getContext(), currentStory.storyItem, BulletinFactory.of(storyContainer, resourcesProvider), resourcesProvider, status -> { + if (storyViewer != null) storyViewer.setOverlayVisible(false); + }); if (popupMenu != null) { popupMenu.dismiss(); } 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 f952e0b82e..c4acf7a2df 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -2,7 +2,6 @@ import android.content.Intent; import android.content.SharedPreferences; -import android.nfc.tech.NfcA; import android.text.TextUtils; import android.util.SparseArray; import android.webkit.MimeTypeMap; @@ -1855,7 +1854,7 @@ public void start() { messageObject.videoEditedInfo = info; duration = info.estimatedDuration / 1000L; if (messageObject.videoEditedInfo.needConvert()) { - MediaController.getInstance().scheduleVideoConvert(messageObject, false, false); + MediaController.getInstance().scheduleVideoConvert(messageObject, false, false, false); } else { boolean rename = new File(messageObject.videoEditedInfo.originalPath).renameTo(new File(path)); if (rename) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java index 3ca228f8f0..d5d7ef68a9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java @@ -1109,7 +1109,7 @@ private void drawInternal(Canvas canvas, float loadingT) { private void drawLayout(StaticLayout staticLayout, Canvas canvas, List spoilers) { if (!spoilers.isEmpty()) { - SpoilerEffect.renderWithRipple(StoryCaptionTextView.this, false, Color.WHITE, 0, patchedLayout, staticLayout, spoilers, canvas, false); + SpoilerEffect.renderWithRipple(StoryCaptionTextView.this, false, Color.WHITE, 0, patchedLayout, 0, staticLayout, spoilers, canvas, false); } else { staticLayout.draw(canvas); } 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 27c345c1ce..1343cb93b4 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 @@ -14,6 +14,7 @@ import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.OvershootInterpolator; @@ -558,4 +559,12 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (filled && isClickable() && getParent() != null) { + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(ev); + } } 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 e612bbbcd4..2046437588 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 @@ -5248,10 +5248,10 @@ public void onCustomEmojiSelected(long documentId, TLRPC.Document document, Stri @Override public void onClearEmojiRecent() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourcesProvider); - builder.setTitle(getString("ClearRecentEmojiTitle", R.string.ClearRecentEmojiTitle)); - builder.setMessage(getString("ClearRecentEmojiText", R.string.ClearRecentEmojiText)); - builder.setPositiveButton(getString("ClearButton", R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); - builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); + builder.setTitle(getString(R.string.ClearRecentEmojiTitle)); + builder.setMessage(getString(R.string.ClearRecentEmojiText)); + builder.setPositiveButton(getString(R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); + builder.setNegativeButton(getString(R.string.Cancel), null); builder.show(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryLinkSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryLinkSheet.java index 58ad3e9cca..e94e336181 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryLinkSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryLinkSheet.java @@ -47,7 +47,6 @@ import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.UItem; import org.telegram.ui.Components.UniversalAdapter; -import org.telegram.ui.Stars.StarsIntroActivity; import java.util.ArrayList; import java.util.regex.Pattern; @@ -74,7 +73,7 @@ public StoryLinkSheet(Context context, Theme.ResourcesProvider resourcesProvider headerPaddingTop = dp(4); headerPaddingBottom = dp(-15); - urlEditText = new EditTextCell(context, getString(R.string.StoryLinkURLPlaceholder), true, -1, resourcesProvider); + urlEditText = new EditTextCell(context, getString(R.string.StoryLinkURLPlaceholder), true, false, -1, resourcesProvider); urlEditText.whenHitEnter(this::processDone); String def = "https://"; @@ -157,7 +156,7 @@ public void afterTextChanged(Editable s) { } }); - nameEditText = new EditTextCell(context, getString(R.string.StoryLinkNamePlaceholder), true, -1, resourcesProvider); + nameEditText = new EditTextCell(context, getString(R.string.StoryLinkNamePlaceholder), true, false, -1, resourcesProvider); nameEditText.whenHitEnter(this::processDone); buttonContainer = new FrameLayout(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index 787b6bd889..3b9f9e6985 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -4572,6 +4572,8 @@ private void setCurrentImage(boolean setThumb) { backgroundImage.setBackground(backgroundDrawable); themeDelegate.applyChatServiceMessageColor(AndroidUtilities.calcDrawableColor(backgroundDrawable), checkBlur(backgroundDrawable), backgroundDrawable, currentIntensity); } + } else if (accent == null) { + backgroundImage.setBackground(Theme.getCachedWallpaper()); } else { if (backgroundGradientDisposable != null) { backgroundGradientDisposable.dispose(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java index 524497990a..76bffc36bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java @@ -127,6 +127,7 @@ import org.telegram.ui.Components.StickerEmptyView; import org.telegram.ui.Components.UnreadCounterTextView; import org.telegram.ui.Components.ViewPagerFixed; +import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate; import java.util.ArrayList; @@ -194,6 +195,7 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N private static final int hide_id = 12; private static final int show_id = 13; private static final int boost_group_id = 14; + private static final int report = 15; private boolean removeFragmentOnTransitionEnd; private boolean finishDialogRightSlidingPreviewOnTransitionEnd; @@ -209,6 +211,7 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N private ActionBarMenuSubItem addMemberSubMenu; private ActionBarMenuSubItem deleteChatSubmenu; private ActionBarMenuSubItem boostGroupSubmenu; + private ActionBarMenuSubItem reportSubmenu; private boolean bottomPannelVisible = true; private float searchAnimationProgress = 0f; private TL_stories.TL_premium_boostsStatus boostsStatus; @@ -242,6 +245,8 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N private boolean openedForForward; private boolean openedForQuote; private boolean openedForReply; + private String voiceChatHash; + private boolean openVideoChat; HashSet excludeTopics; private boolean mute = false; @@ -291,10 +296,32 @@ public TopicsFragment(Bundle bundle) { openedForForward = arguments.getBoolean("forward_to", false); openedForQuote = arguments.getBoolean("quote", false); openedForReply = arguments.getBoolean("reply_to", false); + voiceChatHash = arguments.getString("voicechat", null); + openVideoChat = arguments.getBoolean("videochat", false); topicsController = getMessagesController().getTopicsController(); canShowProgress = !getUserConfig().getPreferences().getBoolean("topics_end_reached_" + chatId, false); } + private boolean lastCallCheckFromServer; + private boolean createGroupCall; + + private void checkGroupCallJoin(boolean fromServer) { + TLRPC.Chat currentChat = getMessagesController().getChat(chatId); + TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(chatId); + boolean openAnimationEnded = true; + if (groupCall == null || voiceChatHash == null && !openVideoChat || !openAnimationEnded) { + if (voiceChatHash != null && fromServer && chatInfo != null && chatInfo.call == null && fragmentView != null && getParentActivity() != null) { + BulletinFactory.of(this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString(R.string.LinkHashExpired)).show(); + voiceChatHash = null; + } + lastCallCheckFromServer = !openAnimationEnded; + return; + } + VoIPHelper.startCall(currentChat, null, voiceChatHash, createGroupCall, !groupCall.call.rtmp_stream, getParentActivity(), TopicsFragment.this, getAccountInstance()); + voiceChatHash = null; + openVideoChat = false; + } + public static BaseFragment getTopicsOrChat(BaseFragment parentFragment, Bundle args) { return getTopicsOrChat(parentFragment.getMessagesController(), parentFragment.getMessagesStorage(), args); } @@ -705,6 +732,9 @@ protected boolean canGenerateLink() { } clearSelectedTopics(); break; + case report: + ReportBottomSheet.openChat(TopicsFragment.this, -chatId); + break; } super.onItemClick(id); } @@ -761,6 +791,7 @@ public void onSearchFilterCleared(FiltersView.MediaFilterData filterData) { addMemberSubMenu = other.addSubItem(add_member_id, R.drawable.msg_addcontact, LocaleController.getString(R.string.AddMember)); boostGroupSubmenu = other.addSubItem(boost_group_id, 0, new RLottieDrawable(R.raw.boosts, "" + R.raw.boosts, AndroidUtilities.dp(24), AndroidUtilities.dp(24)), LocaleController.getString(R.string.BoostingBoostGroupMenu), true, false); createTopicSubmenu = other.addSubItem(create_topic_id, R.drawable.msg_topic_create, LocaleController.getString(R.string.CreateTopic)); + reportSubmenu = other.addSubItem(report, R.drawable.msg_report, LocaleController.getString(R.string.ReportChat)); deleteChatSubmenu = other.addSubItem(delete_chat_id, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveMegaMenu), themeDelegate); avatarContainer = new ChatAvatarContainer(context, this, false); @@ -2525,8 +2556,11 @@ public void onAnimationEnd(Animator animation) { addMemberSubMenu.setVisibility(ChatObject.canAddUsers(chatLocal) ? View.VISIBLE : View.GONE); boostGroupSubmenu.setVisibility(ChatObject.isBoostSupported(chatLocal) && (getUserConfig().isPremium() || ChatObject.isBoosted(chatFull) || ChatObject.hasAdminRights(chatLocal)) ? View.VISIBLE : View.GONE); deleteChatSubmenu.setVisibility(chatLocal != null && !chatLocal.creator && !ChatObject.isNotInChat(chatLocal) ? View.VISIBLE : View.GONE); + reportSubmenu.setVisibility(chatLocal != null && !chatLocal.creator && !ChatObject.hasAdminRights(chatLocal) ? View.VISIBLE : View.GONE); updateCreateTopicButton(true); groupCall = getMessagesController().getGroupCall(chatId, true); + + checkGroupCallJoin(false); } private void setButtonType(int bottomButtonType) { @@ -2546,9 +2580,20 @@ private void updateSubtitle() { this.chatFull = chatFull; String newSubtitle; if (chatFull != null) { - newSubtitle = LocaleController.formatPluralString("Members", chatFull.participants_count); + if (chatFull.participants_count <= 0) { + TLRPC.Chat chat = getMessagesController().getChat(chatId); + if (chat == null) { + newSubtitle = LocaleController.getString(R.string.Loading); + } else if (ChatObject.isPublic(chat)) { + newSubtitle = LocaleController.getString(R.string.MegaPublic).toLowerCase(); + } else { + newSubtitle = LocaleController.getString(R.string.MegaPrivate).toLowerCase(); + } + } else { + newSubtitle = LocaleController.formatPluralString("Members", chatFull.participants_count); + } } else { - newSubtitle = LocaleController.getString(R.string.Loading).toLowerCase(); + newSubtitle = LocaleController.getString(R.string.Loading); } avatarContainer.setSubtitle(newSubtitle); @@ -2688,6 +2733,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (pendingRequestsDelegate != null) { pendingRequestsDelegate.setChatInfo(chatFull, true); } + checkGroupCallJoin((Boolean) args[3]); } } else if (id == NotificationCenter.storiesUpdated) { updateChatInfo(); @@ -2726,6 +2772,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (fragmentContextView != null) { fragmentContextView.checkCall(!fragmentBeginToShow); } + checkGroupCallJoin(false); } } else if (id == NotificationCenter.notificationsSettingsUpdated) { updateTopicsList(false, false); @@ -3848,10 +3895,14 @@ private void setSlideTransitionProgress(float progress) { } } + private boolean openAnimationEnded; + @Override public void onTransitionAnimationStart(boolean isOpen, boolean backward) { super.onTransitionAnimationStart(isOpen, backward); - + if (isOpen) { + openAnimationEnded = false; + } notificationsLocker.lock(); } @@ -3864,6 +3915,10 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { } blurredView.setBackground(null); } + if (isOpen) { + openAnimationEnded = true; + checkGroupCallJoin(lastCallCheckFromServer); + } notificationsLocker.unlock(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java index a6b1b7e4bf..b4b43b1437 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java @@ -29,18 +29,14 @@ 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.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; import org.telegram.ui.Components.BulletinFactory; -import org.telegram.ui.Components.ChatAttachAlertLocationLayout; import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.CrossfadeDrawable; -import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.UItem; import org.telegram.ui.Components.UniversalAdapter; import org.telegram.ui.Components.UniversalFragment; @@ -86,7 +82,7 @@ public void onFragmentDestroy() { @Override public View createView(Context context) { - firstNameEdit = new EditTextCell(context, getString(R.string.EditProfileFirstName), false, -1, resourceProvider) { + firstNameEdit = new EditTextCell(context, getString(R.string.EditProfileFirstName), false, false, -1, resourceProvider) { @Override protected void onTextChanged(CharSequence newText) { super.onTextChanged(newText); @@ -96,7 +92,7 @@ protected void onTextChanged(CharSequence newText) { firstNameEdit.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); firstNameEdit.setDivider(true); firstNameEdit.hideKeyboardOnEnter(); - lastNameEdit = new EditTextCell(context, getString(R.string.EditProfileLastName), false, -1, resourceProvider) { + lastNameEdit = new EditTextCell(context, getString(R.string.EditProfileLastName), false, false, -1, resourceProvider) { @Override protected void onTextChanged(CharSequence newText) { super.onTextChanged(newText); @@ -105,7 +101,7 @@ protected void onTextChanged(CharSequence newText) { }; lastNameEdit.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); lastNameEdit.hideKeyboardOnEnter(); - bioEdit = new EditTextCell(context, getString(R.string.EditProfileBioHint), true, getMessagesController().getAboutLimit(), resourceProvider) { + bioEdit = new EditTextCell(context, getString(R.string.EditProfileBioHint), true, false, getMessagesController().getAboutLimit(), resourceProvider) { @Override protected void onTextChanged(CharSequence newText) { super.onTextChanged(newText); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java index eae08d18b4..eceec10c6d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java @@ -95,6 +95,7 @@ import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.HideViewAfterAnimation; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.PermissionRequest; import org.telegram.ui.Components.voip.AcceptDeclineView; import org.telegram.ui.Components.voip.EmojiRationalLayout; import org.telegram.ui.Components.voip.HideEmojiTextView; @@ -124,6 +125,7 @@ import org.webrtc.TextureViewRenderer; import java.io.ByteArrayOutputStream; +import java.security.Permission; import java.util.ArrayList; import java.util.List; @@ -2600,12 +2602,7 @@ private void setMicrohoneAction(VoIpSwitchLayout bottomButton, VoIPService servi hideUiRunnableWaiting = false; final boolean micMute = !serviceInstance.isMicMute(); if (accessibilityManager.isTouchExplorationEnabled()) { - final String text; - if (micMute) { - text = LocaleController.getString(R.string.AccDescrVoipMicOff); - } else { - text = LocaleController.getString(R.string.AccDescrVoipMicOn); - } + final String text = LocaleController.getString(micMute ? R.string.AccDescrVoipMicOff : R.string.AccDescrVoipMicOn); view.announceForAccessibility(text); } serviceInstance.setMicMute(micMute, false, true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/web/BotWebViewContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/web/BotWebViewContainer.java index 4a09b097a4..2ac5121486 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/web/BotWebViewContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/web/BotWebViewContainer.java @@ -18,6 +18,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -321,6 +322,12 @@ public void setOpener(MyWebView webView) { } } + private static String capitalizeFirst(String str) { + if (str == null) return ""; + if (str.length() <= 1) return str.toUpperCase(); + return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase(); + } + @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) private void setupWebView(MyWebView replaceWith, Object proxy) { if (webView != null) { @@ -376,6 +383,12 @@ private void setupWebView(MyWebView replaceWith, Object proxy) { useragent = useragent.replace("; wv)", ")"); useragent = useragent.replaceAll("\\(Linux; Android.+;[^)]+\\)", "(Linux; Android " + Build.VERSION.RELEASE + "; K)"); useragent = useragent.replaceAll("Version/[\\d\\.]+ ", ""); + if (bot) { + final PackageInfo packageInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); + final int perf = SharedConfig.getDevicePerformanceClass(); + final String perfName = perf == SharedConfig.PERFORMANCE_CLASS_LOW ? "LOW" : perf == SharedConfig.PERFORMANCE_CLASS_AVERAGE ? "AVERAGE" : "HIGH"; + useragent += " Telegram-Android/" + packageInfo.versionName + " (" + capitalizeFirst(Build.MANUFACTURER) + " " + Build.MODEL + "; Android " + Build.VERSION.RELEASE + "; SDK " + Build.VERSION.SDK_INT + "; " + perfName + ")"; + } settings.setUserAgentString(useragent); } catch (Exception e) { FileLog.e(e); @@ -1322,21 +1335,27 @@ public void didReceivedNotification(int id, int account, Object... args) { PopupButton btn = buttonsList.get(0); if (btn.textColorKey >= 0) { TextView textView = (TextView) currentDialog.getButton(AlertDialog.BUTTON_POSITIVE); - textView.setTextColor(getColor(btn.textColorKey)); + if (textView != null) { + textView.setTextColor(getColor(btn.textColorKey)); + } } } if (buttonsList.size() >= 2) { PopupButton btn = buttonsList.get(1); if (btn.textColorKey >= 0) { TextView textView = (TextView) currentDialog.getButton(AlertDialog.BUTTON_NEGATIVE); - textView.setTextColor(getColor(btn.textColorKey)); + if (textView != null) { + textView.setTextColor(getColor(btn.textColorKey)); + } } } if (buttonsList.size() == 3) { PopupButton btn = buttonsList.get(2); if (btn.textColorKey >= 0) { TextView textView = (TextView) currentDialog.getButton(AlertDialog.BUTTON_NEUTRAL); - textView.setTextColor(getColor(btn.textColorKey)); + if (textView != null) { + textView.setTextColor(getColor(btn.textColorKey)); + } } } } catch (JSONException e) { @@ -1366,7 +1385,7 @@ public void didReceivedNotification(int id, int account, Object... args) { try { JSONObject jsonObject = new JSONObject(eventData); delegate.onWebAppSetBackgroundColor(Color.parseColor(jsonObject.optString("color", "#ffffff")) | 0xFF000000); - } catch (JSONException | IllegalArgumentException e) { + } catch (Exception e) { FileLog.e(e); } break; @@ -1397,7 +1416,7 @@ public void didReceivedNotification(int id, int account, Object... args) { delegate.onWebAppSetActionBarColor(themeKey, Theme.getColor(themeKey, resourcesProvider), false); } } - } catch (JSONException e) { + } catch (Exception e) { FileLog.e(e); } break; @@ -1609,7 +1628,7 @@ public void didReceivedNotification(int id, int account, Object... args) { buttonData = eventData; delegate.onSetupMainButton(isVisible, isActive, text, color, textColor, isProgressVisible, hasShineEffect); - } catch (JSONException | IllegalArgumentException e) { + } catch (Exception e) { FileLog.e(e); } break; @@ -1634,7 +1653,7 @@ public void didReceivedNotification(int id, int account, Object... args) { secondaryButtonData = eventData; delegate.onSetupSecondaryButton(isVisible, isActive, text, color, textColor, isProgressVisible, hasShineEffect, position); - } catch (JSONException | IllegalArgumentException e) { + } catch (Exception e) { FileLog.e(e); } break; @@ -2695,116 +2714,121 @@ public MyWebView(Context context, boolean bot) { public boolean onLongClick(View v) { WebView.HitTestResult result = getHitTestResult(); if (result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) { - String url = result.getExtra(); + final String url = result.getExtra(); + AndroidUtilities.runOnUIThread(() -> { - BottomSheet.Builder builder = new BottomSheet.Builder(getContext(), false, null); - String formattedUrl = url; - try { + BottomSheet.Builder builder = new BottomSheet.Builder(getContext(), false, null); + String formattedUrl = url; try { - Uri uri = Uri.parse(formattedUrl); - formattedUrl = Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null); - } catch (Exception e) { - FileLog.e(e, false); - } - formattedUrl = URLDecoder.decode(formattedUrl.replaceAll("\\+", "%2b"), "UTF-8"); - } catch (Exception e) { - FileLog.e(e); - } - builder.setTitleMultipleLines(true); - builder.setTitle(formattedUrl); - builder.setItems(new CharSequence[]{ - LocaleController.getString(R.string.OpenInTelegramBrowser), - LocaleController.getString(R.string.OpenInSystemBrowser), - LocaleController.getString(R.string.Copy) - }, (dialog, which) -> { - if (which == 0) { - loadUrl(url); - } else if (which == 1) { try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - intent.putExtra(android.provider.Browser.EXTRA_CREATE_NEW_TAB, true); - intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); - getContext().startActivity(intent); + Uri uri = Uri.parse(formattedUrl); + formattedUrl = Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null); } catch (Exception e) { - FileLog.e(e); - loadUrl(url); - } - } else if (which == 2) { - AndroidUtilities.addToClipboard(url); - if (botWebViewContainer != null) { - botWebViewContainer.showLinkCopiedBulletin(); + FileLog.e(e, false); } + formattedUrl = URLDecoder.decode(formattedUrl.replaceAll("\\+", "%2b"), "UTF-8"); + } catch (Exception e) { + FileLog.e(e); } + builder.setTitleMultipleLines(true); + builder.setTitle(formattedUrl); + builder.setItems(new CharSequence[]{ + LocaleController.getString(R.string.OpenInTelegramBrowser), + LocaleController.getString(R.string.OpenInSystemBrowser), + LocaleController.getString(R.string.Copy) + }, (dialog, which) -> { + if (which == 0) { + loadUrl(url); + } else if (which == 1) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.putExtra(android.provider.Browser.EXTRA_CREATE_NEW_TAB, true); + intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); + getContext().startActivity(intent); + } catch (Exception e) { + FileLog.e(e); + loadUrl(url); + } + } else if (which == 2) { + AndroidUtilities.addToClipboard(url); + if (botWebViewContainer != null) { + botWebViewContainer.showLinkCopiedBulletin(); + } + } + }); + builder.show(); }); - builder.show(); return true; } else if (result.getType() == HitTestResult.IMAGE_TYPE) { - String imageUrl = result.getExtra(); + final String imageUrl = result.getExtra(); - BottomSheet.Builder builder = new BottomSheet.Builder(getContext(), false, null); - String formattedUrl = imageUrl; - try { + AndroidUtilities.runOnUIThread(() -> { + + BottomSheet.Builder builder = new BottomSheet.Builder(getContext(), false, null); + String formattedUrl = imageUrl; try { - Uri uri = Uri.parse(formattedUrl); - formattedUrl = Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null); - } catch (Exception e) { - FileLog.e(e, false); - } - formattedUrl = URLDecoder.decode(formattedUrl.replaceAll("\\+", "%2b"), "UTF-8"); - } catch (Exception e) { - FileLog.e(e); - } - builder.setTitleMultipleLines(true); - builder.setTitle(formattedUrl); - builder.setItems(new CharSequence[]{ - LocaleController.getString(R.string.OpenInSystemBrowser), - LocaleController.getString(R.string.AccActionDownload), - LocaleController.getString(R.string.CopyLink) - }, (dialog, which) -> { - if (which == 0) { try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(imageUrl)); - intent.putExtra(android.provider.Browser.EXTRA_CREATE_NEW_TAB, true); - intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); - getContext().startActivity(intent); + Uri uri = Uri.parse(formattedUrl); + formattedUrl = Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null); } catch (Exception e) { - FileLog.e(e); - loadUrl(imageUrl); + FileLog.e(e, false); } - } else if (which == 1) { - try { - String filename = URLUtil.guessFileName(imageUrl, null, "image/*"); - if (filename == null) { - filename = "image.png"; + formattedUrl = URLDecoder.decode(formattedUrl.replaceAll("\\+", "%2b"), "UTF-8"); + } catch (Exception e) { + FileLog.e(e); + } + builder.setTitleMultipleLines(true); + builder.setTitle(formattedUrl); + builder.setItems(new CharSequence[]{ + LocaleController.getString(R.string.OpenInSystemBrowser), + LocaleController.getString(R.string.AccActionDownload), + LocaleController.getString(R.string.CopyLink) + }, (dialog, which) -> { + if (which == 0) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(imageUrl)); + intent.putExtra(android.provider.Browser.EXTRA_CREATE_NEW_TAB, true); + intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); + getContext().startActivity(intent); + } catch (Exception e) { + FileLog.e(e); + loadUrl(imageUrl); } + } else if (which == 1) { + try { + String filename = URLUtil.guessFileName(imageUrl, null, "image/*"); + if (filename == null) { + filename = "image.png"; + } - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(imageUrl)); - request.setMimeType("image/*"); - request.setDescription(getString(R.string.WebDownloading)); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); - DownloadManager downloadManager = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE); - if (downloadManager != null) { - downloadManager.enqueue(request); - } + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(imageUrl)); + request.setMimeType("image/*"); + request.setDescription(getString(R.string.WebDownloading)); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); + DownloadManager downloadManager = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE); + if (downloadManager != null) { + downloadManager.enqueue(request); + } + if (botWebViewContainer != null) { + BulletinFactory.of(botWebViewContainer, botWebViewContainer.resourcesProvider) + .createSimpleBulletin(R.raw.ic_download, AndroidUtilities.replaceTags(formatString(R.string.WebDownloadingFile, filename))) + .show(true); + } + } catch (Exception e2) { + FileLog.e(e2); + } + } else if (which == 2) { + AndroidUtilities.addToClipboard(imageUrl); if (botWebViewContainer != null) { - BulletinFactory.of(botWebViewContainer, botWebViewContainer.resourcesProvider) - .createSimpleBulletin(R.raw.ic_download, AndroidUtilities.replaceTags(formatString(R.string.WebDownloadingFile, filename))) - .show(true); + botWebViewContainer.showLinkCopiedBulletin(); } - } catch (Exception e2) { - FileLog.e(e2); - } - } else if (which == 2) { - AndroidUtilities.addToClipboard(imageUrl); - if (botWebViewContainer != null) { - botWebViewContainer.showLinkCopiedBulletin(); } - } + }); + builder.show(); }); - builder.show(); return true; } diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_unlock.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_unlock.png new file mode 100644 index 0000000000000000000000000000000000000000..1b582c2f7485c4481934be4a8cde6d79eeaf4128 GIT binary patch literal 753 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM315>o8i(^Ox z=i3?ky=4Lgj@w>b;1b}Iy->i#z}L!q=QSs%4LlrCOL-Rc{%@G{Um;b2bIE7^2_X*^ zI(i#LnkKPKI(F`l(3ej?U-8_zckg!X?7MTg%s<@So`3I5d0P7YyR&!i+b6BIwf^k# zn>lx6Y-JA2 ze;6h|5S+m_$$x?0)_t+(R_&Y6qqTVX^f!&{Zw)W-Hux5>sqh-y$P2IHdnxeY`jQl* z<_-TOcG&37b+BeUlH;FaC+;5;O0>_mlS)ha^DDXM zjGKIJr&+<24KwYNDzc8foBuLeWnuNPl1V3L#FbQk_mAF^(WMgdL;KL9J;{GK?QZOu z)o5Fg^E+{;hH~BEjdreDBBy6=O4k4DrODj2PDP~SZlLXjz}t(K+zIx1op9&M>KD)6 z+Lc{U&y{}@w03dC@)lXg-v_OJ@U9Xn>@@z7wn=M?TU+$Br{Qk3xBD2kiauY^vBGpF zv+x1S?Ta}pnlv9wtvvX5ZpQP5g%%AvR32Rm>k#ec(Dt3_XhYOH6f ze7!x5zcP89^G2wOP>;RcDSpq-U(Nlwy71+d=@mVzBd>`b&$fQsykEs5YwnW0<$?B3 z>NQeqy))Ksm7jE$jXk%D9m>mV$iXEdB7lpAob~GiVDzk{_<4{mnXd=7Z!K3Wv z?FLe1?wdp=JW^M<*v1>t8e7q>p5b!pM&_AKMV-F!M`M^%!o>r=er`P$wIH|i} z^E!=^!+PhOf5uA}{Bxf1?COp~6>1?ZcbMnAoY=bblZylUskRESKd*KcyD4bzZ%egR=~MzilPNLc%5 z(|@*$n}2;){&hu_*KPVW{Q|jg<=`LIJA&>P?YFmjY_rZS?Zf>P$@xt+?cW}XJ*k%G z`gr30GqIRMLiwBCKFnQnka5q;*^y6_qCQ^9n9zNPugbXN>5sO9S60M@{XVp6f9agv Ze;9V_nf;X&>fa2CCQnyCmvv4FO#mYn;<*3- literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_unlock.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_unlock.png new file mode 100644 index 0000000000000000000000000000000000000000..787cb5328a39a351cae6c6b004258200160bfd9a GIT binary patch literal 987 zcmV<110?*3P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFMM*?KRA>e5noo#LQ5?tL8wM+r zKQly0l9Y{JS&+<%SjeB9rO8s(RMz8zA}U1D3}*JkmxN$5;c;z30A6PexW}A zFTfO70k(pTK+7#E2iaENbz@;V$;-^Y14e$JoC3>QB|&=)+y+{%Q;D9)R`Hx|1lHT8 zL4CW^2?Oj-04+y-{BpG+`T>=J%)D3fCJF3MD}NchoL0pN0p+wYGMY6qj{V@JA)q{# zl_S`mU_-zhm2#rA-1Dvg_#FX8?zrr8>nEa|_eSo95<@Tu{v<@xl$n3beSyK{32Q`- z${^wRY~c7Qab8H7c_l*!FsL$?Bx2;Fa$c@D0| z=s0$d!AZ8%gs0D}+5B0pOA1NLAs{!`AnAn_2uj>Il>;y{(XCRSCe9pq&8t@r_a|IHjr;x4lAjx3lAd!h&5B7o)Aa#j(CaF^d2(v#7jL4;HUjR)e7h=do z(OmE(_Kr*h+8F1H!jQ-%-PcK-c$ZC3$_utweYQ^eHmQEuHbse!rE{1Q-!*_G%Hx&N zJFV(iOKrhi1JI{b?5)$5N4ihP(mABwE}e&O8&-Gl;~J*gM;!iF``~9Ceig*>0n-) zqr?E8Roufidutyg3&6M{dxO3k_`FM7xznA(nQ+%BjXXo?PuuFc^{y?35NxJ+0yNPy z^*Ye^cB;W5d8`GC6vGVq7QRZ1tF|zeLF@t(peT`8JHxVV;{~C7+&T|FfKG{Up95YW zwIo&N7D|r?a`BOW=8*U0%>HSPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS-zVw=JymE9JxlXRj@V!%oW{s9%6)K=+4A{Gi3Mu>$`{EA=%UC)6h z440do@8x~Wg~RTA-FxoYnR##Do2jW{MS&OvdNG4jj2(?em*HmsoB>V)CxOqv2Vf6) z*6a0N;IlghQ5JxEz%Jlo?8p8KtyT#M&I0SeArN95$MLhR6ADQ!0{cJ;qo2jrh=gR8 zf!`KoexUsguw8w!JkIEEx$z<~i7{EeL)$Ijl9njzt9JG~%9<+@GUBq*X3lri4}lY! zFtU#Qs{R}&jsBar+(4QevbN{EMg0XSf=ij>0FIZ&IL+F)L6}z?X-qCE5sn8mk=9*A zu0O6y6w7-ckOq~wWDi4kmi4@dC`9p|ECT`T~x91w<(;=SMf!4crm#^pfXVC zJXPvaRB3*-_`$Jq2*iKorXAqd-Z3jueXsl;2!ArZX!a}S5QvW~OygsVoF@It_))QQ z2y{v?`Y6h&i_*W09~Cc$K*t56KcbwvDE-U$QSovJ6h$atFrPY_Cd+1<_xCmkbQ@X! zUuOJdIhiG$j>%YgIKq|e74Ch`VaR#lHOfCdhFiNfULa;ziSpcx` zELs(Tia-_xEX_$bXT(qS!s#bq51aP4Q~{!2JtO%!khuX|1umu{ z7U}0D#yL#+KsUtz-`Ob=KA1|7c~zbfwaC}_Y^9F{FNF1MinQ z_u|lJ22o+2kT8u01Rj_bHTzC(@(_c}AsuDRpw1m$(02H-ib5op<1gFl;PyMNo results No results found for \"%s\". No results found for %s + There were no results for \"%s\".\nTry a new search. Welcome to Telegram Recently viewed HIDE @@ -537,8 +538,9 @@ Channel created un1 sent you a gift for **un2** You have sent a gift for **un2** - Telegram Premium - for %1$s + %d Month Premium + %d Months Premium + Subscription for exclusive Telegram features. View Congratulations! You won a prize in a giveaway organized by **un1**.\n\nYour prize is **%d Star**. @@ -655,6 +657,7 @@ You cannot edit the rights of this admin. You cannot edit this permission. This permission is not available in public groups. + This permission is not available in discussion groups. Removed by %1$s User Permissions What can this user do? @@ -976,6 +979,8 @@ un1 changed forum to group un1 created topic un2 un1 changed topic name from un2 to un3 + un1 closed topic un2 + un1 reopened topic un2 un1 delete topic un2 un1 pin topic un2 un1 unpin topic un2 @@ -1160,6 +1165,7 @@ Unsupported attachment Set self-destruct timer Service notifications + Verification Codes Getting Link Info... OPEN IN... Open in... @@ -1311,6 +1317,7 @@ Delete for %1$s Delete for all members Text copied to clipboard + "%s" copied to clipboard Code copied to clipboard Hold to record audio. Hold to record audio. Tap to switch to video. @@ -1446,6 +1453,7 @@ View Thread Choose date This chat helps you keep track of replies to your comments in Channels. + This chat is used to receive verification codes from third-party services. Sorry, this post has been removed from the discussion group. UNPIN ALL MESSAGES HIDE PINNED MESSAGES @@ -1503,6 +1511,8 @@ 📅 You: %1$s 📅 You %1$s: %2$s + %2$s sent you a Gift worth of %1$d Star + %2$s sent you a Gift worth of %1$d Stars %1$s sent you %2$s %1$s sent you an album %1$s forwarded you %2$s @@ -1678,12 +1688,14 @@ Sorted by last seen time Add %1$s Phone number - You have no contacts on Telegram yet - Invite friends to try Telegram - Search people by username + You have no contacts\non Telegram yet + Invite friends to try Telegram or search\npeople by username. + Invite Friends > New contact Phone number **%1$s** is not in your contacts list. Do you want to add it? Add contact + %d sold + %d left Add people... You will be able to add more users after you finish creating the group and convert it to a supergroup. @@ -3001,6 +3013,9 @@ We will notify you once someone is within %1$s from you. Proximity alert cancelled + Quality + Auto + Source Speed Slow Very slow @@ -3422,6 +3437,7 @@ This will remove your contacts from the Telegram servers.\n\nIf \'**Sync Contacts**\' is enabled, contacts will be re-synced. Sending video... + Converting video... Sending GIF... bot @@ -3718,6 +3734,7 @@ Are you sure you want to delete these messages for everyone? Unsend My Messages Also delete for %1$s + Delete for both sides where possible Also clear history for %1$s Send message Do you want to send this message to **%1$s**? @@ -4067,6 +4084,8 @@ End live stream VIEW LIVE STREAM Live Stream + LIVE + watching Scheduled Live Stream Open live stream Sorry, you can\'t join live streams as an anonymous administrator. @@ -4139,7 +4158,13 @@ Voice chat sound unmuted. Members of this group will be notified once you start the voice chat. Subscribers of this channel will be notified once you start the live stream. + To stream video with another app,\nenter the server URL and Stream Key\nin your streaming app. You will be displayed as: + Stream settings + You can also stream with **another app >** + Once you start broadcasting in your streaming app, tap Start Streaming below. + Server URL + Stream Key Start Voice Chat Schedule Voice Chat Join Live Stream @@ -4147,6 +4172,7 @@ Live stream sound muted. Live stream sound unmuted. Start Live Stream + Start Streaming Schedule Live Stream Start Now Set Reminder @@ -4376,6 +4402,8 @@ %1$d months %1$d-month %1$d-months + %1$d-month + %1$d-months %1$d-month %1$d-month **%1$d** month @@ -5004,6 +5032,7 @@ %3$s to your GIF in %2$s %2$s to your story New reaction to your story + Story Reaction Blur in chat Allow background activity @@ -5179,6 +5208,8 @@ You can review the list of features and terms of use for Telegram Premium *here*. Gift Premium Premium Gifting + Send a Gift + Send a Gift Activate For Free You already have Telegram Premium You can activate this gift code after %1$s or **send the link** to a friend. @@ -5209,6 +5240,7 @@ What\'s included Send gifts **to your friends!** 🎄 Gift Telegram Premium + Gift Premium or Stars Let **%1$s** enjoy exclusive features of Telegram with **Telegram Premium**. Telegram Premium Go **beyond the limits**, get exclusive features and support us by subscribing to **Telegram Premium**. @@ -5964,8 +5996,8 @@ Wallpaper Set a new chat Wallpaper Set a same chat Wallpaper - By launching this mini app, you agree to the **Terms of Service for Mini Apps**. - https://telegram.org/tos/stars + By launching this mini app, you agree to the **Terms of Service for Mini Apps**. + https://telegram.org/tos/mini-apps More about this bot Tap to view this theme in the day mode. Tap to view this theme in the night mode. @@ -7446,9 +7478,9 @@ Let your contacts know when you’re celebrating You can always set your birthday in profile settings. It’s %s’s **birthday** today! 🎂 - Gift them Telegram Premium. + Send them a Gift. %d contacts have **birthdays** today! 🎂 - Gift them Telegram Premium. + Send them a Gift. 🎂 Birthday today Birthday yesterday Birthday tomorrow @@ -7604,7 +7636,7 @@ You can update the visibility of sensitive media in **Chat Settings > Show 18+ Content** Your Stars Telegram Stars - Buy Stars to unlock content and service\nin miniapps on Telegram. + Buy Stars to unlock content and services\nin miniapps on Telegram. **More about Stars >** Choose package Gift Stars to Friends %d Star @@ -7616,6 +7648,7 @@ Incoming Outgoing In-App Purchase + Hidden User Unknown User https://fragment.com/stars Stars Top-Up Bot @@ -7641,6 +7674,7 @@ Buy **Stars** and subscribe to **%s** and other channels. Buy **Stars** to keep your subscription for **%s**. Buy **Stars** to send paid reactions to **%s** and other channels. + Buy **Stars** to send gifts to **%s** and other contacts. Buy **Stars** to keep your channel subscriptions. Buy **Stars** to keep your channel subscriptions. Buy **Stars** to keep your subscriptions active for the next 12 months. @@ -8016,4 +8050,133 @@ Giveaway Date Until + Gift %s + Gift Premium + Give **%s** access to exclusive features with Telegram Premium. + See Features > + Gift Stars + Give **%s** gifts that can be kept on the profile or converted to Stars. + What are Stars > + Send a Gift + Enter Message + Enter Message (Optional) + Only %s will see your message. + Hide My Name + You can hide your name and message from visitors to %1$s`s profile. %1$s will still see your name and message. + Send a Gift for ⭐️%d + Send a Gift for ⭐️%d + Send a Gift for %s + Gift from + %s received a gift! + You received a gift! + Display this gift on your page or convert it to %d Star. + Display this gift on your page or convert it to %d Stars. + You kept this gift on your page. + You converted this gift to %d Star. + You converted this gift to %d Stars. + **%2$s** can display this gift on their page or convert it to %1$d Star. + **%2$s** can display this gift on their page or convert it to %1$d Stars. + %d Star + %d Stars + Gifts + These gifts were sent to you by other users.\nTap on a gift to convert it to Stars or change its privacy settings. + %d gift + %d gifts + Send Gifts to Friends + All Gifts + Limited + limited + Limited + 1 of %s + Gift sent! + You spent **%1$d** Star from your balance. + You spent **%1$d** Stars from your balance. + Sent Gift + Gift + Received Gift + Premium + You can keep this gift in your Profile or convert it to **%d** Star. + You can keep this gift in your Profile or convert it to **%d** Stars. + %2$s can keep this gift in profile or convert it to **%1$d** Star. + %2$s can keep this gift in profile or convert it to **%1$d** Stars. + You converted this gift to **%d** Star. + You converted this gift to **%d** Stars. + You kept this gift in your Profile. + %2$s converted this gift to **%d** Star. + %2$s converted this gift to **%d** Stars. + %1$s kept this gift in your Profile. + Only you can see the senderʼs name. + This gift is visible to visitors of your page. + This gift is visible to visitors of your page. **View >** + This gift is hidden. Only you can see it. + **More about Stars >** + From + To + Availability + %1$d of %2$s left + %1$d of %2$s left + None of %1$d left + None of %1$d left + Display on my Page + Hide from my Page + Convert to %d Star + Convert to %d Stars + Convert Gift to Stars + Do you want to convert this gift from **%2$s** to **%3$s**?\n\nConversion is available for the next **%1$d day**.\n\nThis action cannot be undone. This will permanently destroy the gift. + Do you want to convert this gift from **%2$s** to **%3$s**?\n\nConversion is available for the next **%1$d days**.\n\nThis action cannot be undone. This will permanently destroy the gift. + %d Star + %d Stars + Convert + sold out + What are Stars? + Telegram Stars allow users to: + Send Gifts to Friends + Give your friends gifts that can be kept on their profiles or converted to Stars. + Use Stars in miniapps + Buy additional content and services in Telegram miniapps. **See Examples >** + Unlock content in channels + Get access to paid content and services in Telegram channels. + Send Star reactions + Support your favorite channels by sending Star reactions to their posts. + Got It + Gift Shown + Gift is now visible in **your profile**. + Gift Hidden + Gift is now hidden in **your profile**. + Converted Gift + %d Star was sent to your balance + %d Star were sent to your balance + Sold Out! + All %d gifts were already sold. + All %d gifts were already sold. + Report Story + Report + Add Comment + Add Comment (Optional) + Please help us by telling what is wrong with the message you have selected. + Please help us by telling what is wrong with the message you have selected. + Please help us by telling what is wrong with the user you have selected. + Please help us by telling what is wrong with the group you have selected. + Please help us by telling what is wrong with the channel you have selected. + Send Report + Telegram moderators will review your report. Thank you! + Refunded Sent Gift + Refunded Converted Gift + Converted Gift + Gift + sent a Gift worth of %d Star + sent a Gift worth of %d Stars + your balance + Buy Stars + Buy More Stars + more + Unavailable + This gift has been sold out + First Sale + Last Sale + Value + Value + send a gift + sell for %d Star + sell for %d Stars \ No newline at end of file diff --git a/TMessagesProj_App/build.gradle b/TMessagesProj_App/build.gradle index b6bdcad1fc..e1a5c072ed 100644 --- a/TMessagesProj_App/build.gradle +++ b/TMessagesProj_App/build.gradle @@ -71,7 +71,7 @@ android { minifyEnabled true shrinkResources false multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' } diff --git a/TMessagesProj_AppHuawei/build.gradle b/TMessagesProj_AppHuawei/build.gradle index afd27f9dfa..8a5393c8a6 100644 --- a/TMessagesProj_AppHuawei/build.gradle +++ b/TMessagesProj_AppHuawei/build.gradle @@ -78,7 +78,7 @@ android { minifyEnabled false shrinkResources false multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' } release { diff --git a/TMessagesProj_AppStandalone/build.gradle b/TMessagesProj_AppStandalone/build.gradle index 81ffb8efe9..8c1b9b64c8 100644 --- a/TMessagesProj_AppStandalone/build.gradle +++ b/TMessagesProj_AppStandalone/build.gradle @@ -72,7 +72,7 @@ android { applicationIdSuffix ".web" minifyEnabled false multiDexEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro' ndk.debugSymbolLevel = 'FULL' } standalone { diff --git a/gradle.properties b/gradle.properties index 448f7e53b0..dc6f5e00df 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=5244 -APP_VERSION_NAME=11.1.3 +APP_VERSION_CODE=5335 +APP_VERSION_NAME=11.2.3 APP_PACKAGE=org.telegram.messenger IS_PRIVATE=false RELEASE_KEY_PASSWORD=android